如何将 JDK6 ToolProvider 和 JavaCompiler 与上下文类加载器一起使用?
我的用例是使用 JDK 6 中提供的 ToolProvider 和 JavaCompiler 类从 java 程序编译生成的源文件。源文件包含对上下文类加载器(它在 J2EE 容器中运行)中的类的引用,但不包含对系统类加载器中的类的引用。 我的理解是,默认情况下 ToolProvider 将使用系统类加载器创建 JavaCompiler 实例。
有没有办法指定JavaCompiler使用的类加载器?
我尝试了这种方法,修改自 IBM DeveloperWorks 上的某些内容:
FileManagerImpl fm =
new FileManagerImpl(compiler.getStandardFileManager(null, null, null););
FileManagerImpl 定义为:
static final class FileManagerImpl
extends ForwardingJavaFileManager<JavaFileManager> {
public FileManagerImpl(JavaFileManager fileManager) {
super(fileManager);
}
@Override
public ClassLoader getClassLoader(JavaFileManager.Location location) {
new Exception().printStackTrace();
return Thread.currentThread().getContextClassLoader();
}
}
堆栈跟踪表明它在注释处理期间仅调用一次。 我验证了要编译的源文件中引用的类不在系统类路径上,但可以从上下文类加载器中获取。
My usage case is compiling generated source files from a java program using the ToolProvider and JavaCompiler classes provided in JDK 6. The source files contain references to classes in the context classloader (it runs in a J2EE container), but not in the system classloader. My understanding is that by default the ToolProvider will create the JavaCompiler instance with the system classloader.
Is there a way to specify a classloader for JavaCompiler to use?
I tried this approach, modified from something on IBM DeveloperWorks:
FileManagerImpl fm =
new FileManagerImpl(compiler.getStandardFileManager(null, null, null););
with FileManagerImpl defined as:
static final class FileManagerImpl
extends ForwardingJavaFileManager<JavaFileManager> {
public FileManagerImpl(JavaFileManager fileManager) {
super(fileManager);
}
@Override
public ClassLoader getClassLoader(JavaFileManager.Location location) {
new Exception().printStackTrace();
return Thread.currentThread().getContextClassLoader();
}
}
The stacktrace indicates it's only called once during annotation processing. I verified the class referenced in the source file to be compiled is not on the system classpath but is available from the context classloader.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您知道 contextclassloader 已知的文件的类路径,则可以将它们传递给编译器:
此示例假设您正在使用 URLClassloader(它允许您检索类路径),但如果需要,您可以插入自己的类路径到。
If you know the classpath to the files that are known to the contextclassloader you can pass them to the compiler:
This example assumes you're using a URLClassloader (which allows you to retrieve the classpath) but you could insert your own classpath if you wanted to.
另一种选择是使用 Commons JCI。
Another option is to use Commons JCI.
您在这里问两个单独的问题。
一是如何编译系统类路径中找不到的类。 通过将“-classpath”命令行参数传递给编译器可以轻松解决这个问题(正如 Leihca 首先提到的)。
第二个是如何在线程上下文类加载器上实例化 ToolProvider 和 JavaCompiler。 在撰写本文时,这是一个未解决的问题:从自定义类加载器使用 javax.tools.ToolProvider?
You're asking two separate questions here.
One is how to compile classes not found in the system classpath. This is easily solved by passing the "-classpath" command-line argument to the compiler (as first mentioned by Leihca).
The second is how to instantiate ToolProvider and JavaCompiler on the thread context classloader. At the time of this writing, this is an unsolved question: Using javax.tools.ToolProvider from a custom classloader?