4

I have been trying to compile some Java Classes in a String using java. I have used javax.tools.JavaCompiler to compile the Classes in the Strings.

I have made instances of SimpleJavaFileObject by a Subclass that I have made of 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;
    }
}

and I have made Instances of this class, added it to an ArrayList, then Got the

ToolProvider.SystemJavaCompiler();

and added compilation options. and then Compiled

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);
}

I have tested this with 3 classes that have circular dependency. it gives the error that it cannot find the symbol of a reference. it seems that unlike javac, this Compiler looks at each item in the list individually and tries to compile each alone.

how to achieve the same result as Javac using this compiler?? Someone please point me in the right direction :) Thanks.

4

2 回答 2

0

以下代码对我来说成功运行(与 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
于 2016-04-14T08:59:21.547 回答
0

我找到了解决问题的方法,

在编译过程中,我创建了一个 ArrayList 来保存 SimpleJavaFileObject(要编译的类)实例,而是添加了一个 LinkedList。

使用链接列表可以正常工作:)

于 2016-04-14T12:17:43.367 回答