java - 使用 javax.tools.JavaCompiler 编译循环依赖类

标签 java compilation javac java-compiler-api javacompiler

我一直在尝试使用 java 将一些 Java 类编译成字符串。 我使用 javax.tools.JavaCompiler 来编译字符串中的类。

我已经通过我用 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;
    }
}

我已经创建了这个类的实例,将它添加到一个 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 个具有循环依赖的类对此进行了测试。它给出了找不到引用符号的错误。似乎与 javac 不同,此编译器单独查看列表中的每个项目并尝试单独编译每个项目。

如何使用此编译器实现与 Javac 相同的结果?? 有人请指出我正确的方向:) 谢谢。

最佳答案

以下代码为我成功运行(与 OP 的代码几乎相同,只是用合理的替代品替换 undefined symbol ):

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

关于java - 使用 javax.tools.JavaCompiler 编译循环依赖类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36617513/

相关文章:

java - 使用 Spring 进行海量多文件上传

java - 如何在 java 中创建一个复杂的 json 对象?

python - 在 Python 与 C 中实现一个函数

linux - autoconf/configure 在哪里寻找包含文件

matlab - 为Matlab编译Windows下的Shogun工具箱

java - 动态添加多个水平线性布局到选项卡

java - 正则表达式匹配引号中的字符串,里面有双引号

java-8 - javac -parameters 标志的缺点

ant - 使用 Ant 编译基于单个文件及其依赖项的项目

java - 为java编译设置slf4j的类路径