使用 javax.tools.JavaCompiler 编译循环依赖 类
Compile Circular Dependency classes using javax.tools.JavaCompiler
我一直在尝试使用 java 在字符串中编译一些 Java 类。
我已经使用 javax.tools.JavaCompiler 来编译字符串中的 类。
我已经通过一个 Subclass 创建了 SimpleJavaFileObject 的实例,我创建了一个 SimpleJavaFileObject.
import javax.tools.SimpleJavaFileObject;
import java.net.URI;
public class JavaSourceFromString extends SimpleJavaFileObject {
final String code;
public JavaSourceFromString(String name, String code) {
super( URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension),Kind.SOURCE);
this.code = code;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return code;
}
}
我已经制作了这个 class 的实例,将它添加到 ArrayList,然后得到了
ToolProvider.SystemJavaCompiler();
并添加了编译选项。然后编译
Iterable<? extends JavaFileObject> fileObjects = jsfsList;
JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
if (jc == null) throw new Exception("Compiler unavailable");
List<String> options = new ArrayList<>();
options.add("-d");
options.add(Config.getProperty("DESTINATION_PATH"));
options.add("-classpath");
URLClassLoader urlClassLoader = (URLClassLoader)Thread.currentThread().getContextClassLoader();
StringBuilder sb = new StringBuilder();
for (URL url : urlClassLoader.getURLs()) {
sb.append(url.getFile()).append(File.pathSeparator);
}
sb.append(PiranhaConfig.getProperty("DESTINATION_PATH"));
options.add(sb.toString());
StringWriter output = new StringWriter();
boolean success = jc.getTask(output, null, null, options, null, fileObjects).call();
if (success) {
LOG.info("Class [" + compiledClasses + "] has been successfully compiled");
} else {
throw new Exception("Compilation failed :" + output);
}
我已经用 3 个具有循环依赖性的 classes 测试了它。它给出了找不到引用符号的错误。似乎与 javac 不同,此编译器单独查看列表中的每个项目并尝试单独编译每个项目。
如何使用此编译器获得与 Javac 相同的结果??
有人请指出我正确的方向:)
谢谢。
以下代码对我来说运行成功(与 OP 的代码几乎相同,只是用合理的替代品替换未定义的符号):
import java.io.File;
import java.io.StringWriter;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.ToolProvider;
class CircularDeps {
public static void main(String[] args) throws Exception {
Iterable<? extends JavaFileObject> fileObjects = Arrays.asList(
new JavaSourceFromString(
"A",
"package packageA; public class A { packageB.B b; }"),
new JavaSourceFromString(
"B",
"package packageB; public class B { packageC.C c; }"),
new JavaSourceFromString(
"C",
"package packageC; public class C { packageA.A a; }")
);
JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
if (jc == null) throw new Exception("Compiler unavailable");
List<String> options = new ArrayList<>();
options.add("-d");
options.add(args[0]);
options.add("-classpath");
URLClassLoader urlClassLoader = (URLClassLoader)Thread.currentThread().getContextClassLoader();
StringBuilder sb = new StringBuilder();
for (URL url : urlClassLoader.getURLs()) {
sb.append(url.getFile()).append(File.pathSeparator);
}
sb.append("output");
options.add(sb.toString());
StringWriter output = new StringWriter();
boolean success = jc.getTask(output, null, null, options, null, fileObjects).call();
if (success) {
System.out.println("Classes has been successfully compiled");
} else {
throw new Exception("Compilation failed :" + output);
}
}
}
输出:
Classes has been successfully compiled
我找到了问题的解决方案,
在编译过程中,我创建了一个 ArrayList 来保存 SimpleJavaFileObject(类 编译)实例,而不是我添加了一个 LinkedList。
使用 link 列表效果很好:)
我一直在尝试使用 java 在字符串中编译一些 Java 类。 我已经使用 javax.tools.JavaCompiler 来编译字符串中的 类。
我已经通过一个 Subclass 创建了 SimpleJavaFileObject 的实例,我创建了一个 SimpleJavaFileObject.
import javax.tools.SimpleJavaFileObject;
import java.net.URI;
public class JavaSourceFromString extends SimpleJavaFileObject {
final String code;
public JavaSourceFromString(String name, String code) {
super( URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension),Kind.SOURCE);
this.code = code;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return code;
}
}
我已经制作了这个 class 的实例,将它添加到 ArrayList,然后得到了
ToolProvider.SystemJavaCompiler();
并添加了编译选项。然后编译
Iterable<? extends JavaFileObject> fileObjects = jsfsList;
JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
if (jc == null) throw new Exception("Compiler unavailable");
List<String> options = new ArrayList<>();
options.add("-d");
options.add(Config.getProperty("DESTINATION_PATH"));
options.add("-classpath");
URLClassLoader urlClassLoader = (URLClassLoader)Thread.currentThread().getContextClassLoader();
StringBuilder sb = new StringBuilder();
for (URL url : urlClassLoader.getURLs()) {
sb.append(url.getFile()).append(File.pathSeparator);
}
sb.append(PiranhaConfig.getProperty("DESTINATION_PATH"));
options.add(sb.toString());
StringWriter output = new StringWriter();
boolean success = jc.getTask(output, null, null, options, null, fileObjects).call();
if (success) {
LOG.info("Class [" + compiledClasses + "] has been successfully compiled");
} else {
throw new Exception("Compilation failed :" + output);
}
我已经用 3 个具有循环依赖性的 classes 测试了它。它给出了找不到引用符号的错误。似乎与 javac 不同,此编译器单独查看列表中的每个项目并尝试单独编译每个项目。
如何使用此编译器获得与 Javac 相同的结果?? 有人请指出我正确的方向:) 谢谢。
以下代码对我来说运行成功(与 OP 的代码几乎相同,只是用合理的替代品替换未定义的符号):
import java.io.File;
import java.io.StringWriter;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.ToolProvider;
class CircularDeps {
public static void main(String[] args) throws Exception {
Iterable<? extends JavaFileObject> fileObjects = Arrays.asList(
new JavaSourceFromString(
"A",
"package packageA; public class A { packageB.B b; }"),
new JavaSourceFromString(
"B",
"package packageB; public class B { packageC.C c; }"),
new JavaSourceFromString(
"C",
"package packageC; public class C { packageA.A a; }")
);
JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
if (jc == null) throw new Exception("Compiler unavailable");
List<String> options = new ArrayList<>();
options.add("-d");
options.add(args[0]);
options.add("-classpath");
URLClassLoader urlClassLoader = (URLClassLoader)Thread.currentThread().getContextClassLoader();
StringBuilder sb = new StringBuilder();
for (URL url : urlClassLoader.getURLs()) {
sb.append(url.getFile()).append(File.pathSeparator);
}
sb.append("output");
options.add(sb.toString());
StringWriter output = new StringWriter();
boolean success = jc.getTask(output, null, null, options, null, fileObjects).call();
if (success) {
System.out.println("Classes has been successfully compiled");
} else {
throw new Exception("Compilation failed :" + output);
}
}
}
输出:
Classes has been successfully compiled
我找到了问题的解决方案,
在编译过程中,我创建了一个 ArrayList 来保存 SimpleJavaFileObject(类 编译)实例,而不是我添加了一个 LinkedList。
使用 link 列表效果很好:)