本文介绍了如何将JDK6 ToolProvider和JavaCompiler与上下文类加载器一起使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的用例是使用JDK 6中提供的ToolProvider和JavaCompiler类从java程序编译生成的源文件。源文件包含对上下文类加载器中的类的引用(它在J2EE容器中运行),但不包含在系统类加载器。我的理解是,默认情况下,ToolProvider将使用系统类加载器创建JavaCompiler实例。

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.

有没有办法为JavaCompiler指定要使用的类加载器?

Is there a way to specify a classloader for JavaCompiler to use?

我尝试过这种方法,在IBM DeveloperWorks上修改过:

I tried this approach, modified from something on IBM DeveloperWorks:

FileManagerImpl fm =
    new FileManagerImpl(compiler.getStandardFileManager(null, null, null););

将FileManagerImpl定义为:

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.

推荐答案

如果您知道contextclassloader已知的文件的类路径,则可以将它们传递给编译器:

If you know the classpath to the files that are known to the contextclassloader you can pass them to the compiler:

    StandardJavaFileManager fileManager = compiler.getStandardFileManager(this /* diagnosticlistener */, null, null);
// get compilationunits from somewhere, for instance via fileManager.getJavaFileObjectsFromFiles(List<file> files)
List<String> options = new ArrayList<String>();
options.add("-classpath");
StringBuilder sb = new StringBuilder();
URLClassLoader urlClassLoader = (URLClassLoader) Thread.currentThread().getContextClassLoader();
for (URL url : urlClassLoader.getURLs())
    sb.append(url.getFile()).append(File.pathSeparator);
options.add(sb.toString());
CompilationTask task = compiler.getTask(null, fileManager, this /* diagnosticlistener */, options, null, compilationUnits);
task.call();

此示例假设您使用的是URLClassloader(允许您检索类路径),但您可以如果你愿意,可以插入自己的类路径。

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.

这篇关于如何将JDK6 ToolProvider和JavaCompiler与上下文类加载器一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 20:30