java - 在这些类上,为具有依赖关系的类和类在内存中动态编译

  显示原文与译文双语对照的内容

我有一个类名和类源代码列表。 我需要在内存中编译这些类以便我可以在程序中使用它们。 除非该类需要另一个必须编译的类,否则编译类很好。 例如如果我有类


package example;
public class A {
 public A() {
 doSomething();
 }
}

如果我必须在后面编译该类,则该类正常运行:


package example;
public class B {
 private A holderForA;
 public B() {
 this.holderForA = new A();
 }
}

B 将无法成功编译。

下面是我的编译代码( 代码是前面提到的代码列表),其中包含。


JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
for(String key : code.keySet()) {
 CODE = code.get(key);
 NAME = key;

 JavaFileObject file = new JavaSourceFromString(NAME, CODE);
 Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file);
 CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, compilationUnits);
 System.out.println("The task completed:" + task.call() +" for" + NAME);
}

第一个类返回 true,第二个返回 false 。 如果我设置了像A 和B 这样的多个类,类型类就会工作,类型类会失败。 我需要做什么?

时间:

我相信你的问题在JavaSourceFromString类中,它需要为类名编码 URI:


@Test
public void test(){
 Map<String, String> code = new HashMap<String, String>();

 code.put("example.A",
"package example;n" +
"public class A {n" +
" public A() {n" +
" doSomething();n" +
" }n" +
"}");

 code.put("example.B",
"package example;n" +
"public class B {n" +
" private A holderForA;n" +
" public B() {n" +
" this.holderForA = new A();n" +
" }n" +
"}");

 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
 DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
 for(String key : code.keySet()) {
 String toCompile = code.get(key);

 JavaFileObject file = new Source(key, JavaFileObject.Kind.SOURCE, toCompile);
 Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file);
 JavaCompiler.CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, compilationUnits);
 assertTrue(task.call());//passes every time
 }
}

public class Source extends SimpleJavaFileObject {
 private final String content;

 public Source(String name, Kind kind, String content) {
 super(URI.create("memo:///" + name.replace('.', '/') + kind.extension), kind);
 this.content = content;
 }

 @Override
 public CharSequence getCharContent(boolean ignore) {
 return this.content;
 }
}

...