微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何将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();
   }

}

堆栈跟踪表明它仅在注释处理期间调用一次.我验证了要编译的源文件中引用的类不在系统类路径中,但可以从上下文类加载器中获得.

解决方法

如果您知道contextclassloader已知的文件的类路径,则可以将它们传递给编译器:
StandardJavaFileManager fileManager = compiler.getStandardFileManager(this /* diagnosticlistener */,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,compilationunits);
task.call();

此示例假设您正在使用urlclassloader(允许您检索类路径),但如果您愿意,可以插入自己的类路径.

原文地址:https://www.jb51.cc/java/120379.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐