我正在尝试编写一个利用Tree API的程序(参见https://weblogs.java.net/blog/2006/09/16/hacking-javac)。基本的想法是,您创建JavaCompiler
并使用它来获得JavaCompiler.CompilationTask
。返回的CompilationTask
实际上是JavacTaskImpl
的实例(请参阅下面的代码)。但是当我尝试将返回的CompilationTask
转换为JavacTaskImpl
时,我得到NoClassDefFoundError
。
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import com.sun.tools.javac.api.JavacTaskImpl;
public class Main {
public static void main(String[] args) {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> fileObjects = fileManager.getJavaFileObjects("Test.java");
CompilationTask task = compiler.getTask(null, fileManager, null, null, null, fileObjects);
// Prove that this is indeed an instance of JavacTaskImpl.
System.out.println("Task.getClass(): " + task.getClass());
JavacTaskImpl javacTask = (JavacTaskImpl) task;
}
}
您可以使用
编译此代码$JAVA_HOME/bin/javac Main.java -cp $JAVA_HOME/lib/tools.jar
但是使用
运行代码$JAVA_HOME/bin/java Main -cp $JAVA_HOME/lib/tools.jar
产生以下输出:
Task.getClass(): class com.sun.tools.javac.api.JavacTaskImpl
Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/tools/javac/api/JavacTaskImpl
at Main.main(Main.java:19)
Caused by: java.lang.ClassNotFoundException: com.sun.tools.javac.api.JavacTaskImpl
at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
... 1 more
如何摆脱此错误?
答案 0 :(得分:0)
您必须在JavaCompiler.getTask
中设置选项(请参阅JavaCompiler javadoc)。最简单的方法是使用System属性:
import com.sun.tools.javac.api.JavacTaskImpl;
import java.util.Arrays;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class Main {
public static void main(String[] args) {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> fileObjects = fileManager.getJavaFileObjects("Test.java");
String classPath = System.getProperty("java.class.path");
CompilationTask task = compiler.getTask(null, fileManager, null,
Arrays.asList("-classpath", classPath),
null, fileObjects);
// Prove that this is indeed an instance of JavacTaskImpl.
System.out.println("Task.getClass(): " + task.getClass());
JavacTaskImpl javacTask = (JavacTaskImpl) task;
}
}