我一直在尝试使用
java在String中编译一些
Java类.
我使用javax.tools.JavaCompiler来编译字符串中的类.
我使用javax.tools.JavaCompiler来编译字符串中的类.
我用SimpleJavaFileObject制作的Subclass创建了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,options,fileObjects).call(); if (success) { LOG.info("Class [" + compiledClasses + "] has been successfully compiled"); } else { throw new Exception("Compilation Failed :" + output); }
我用3个具有循环依赖性的类测试了这个.它给出了错误,它无法找到引用的符号.似乎与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,fileObjects).call(); if (success) { System.out.println("Classes has been successfully compiled"); } else { throw new Exception("Compilation Failed :" + output); } } }
输出:
Classes has been successfully compiled