使用自定义类加载器中的javax.tools.ToolProvider?

似乎不可能使用Ant或Webstart所需的自定义类加载器中的javax.tools.ToolProvider : http ://bugs.sun.com/view_bug.do?video_id = 6548428

javax.tools.ToolProvider.getSystemJavaCompiler()javax.tools.JavaCompiler加载到URLClassLoader中,其父级是系统类加载器。 API似乎不允许用户指定父类加载器。

如何从自定义类加载器中使用javax.tools.JavaCompiler

例如:

  • Ant加载MyParserTask
  • MyParserTask解析Java源代码
  • AntClassLoader由委托给系统类加载器的AntClassLoader加载
  • javax.tools.JavaCompilerURLClassLoader加载,代理到系统类加载器

稍后, MyParserTask调用:

 javax.tools.CompilationTask task = compiler.getTask(...); com.sun.source.util.JavacTask javacTask = (com.sun.source.util.JavacTask) task; javacTask.parse().next().accept(visitor, unused); // parsing happens here 
  • 看到这两个类如何驻留在不同的类加载器上, JavacTask没有办法在不获取ClassCastException错误的情况下与JavacTask进行交互。

有任何想法吗?

我有完全相同的问题。 我正在使用自定义ant任务来扫描AST以进行某些类型的方法调用。 我的解决方案可能不适合您,我自己实例化编译器而不是使用ToolProvider。

我换了

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

JavaCompiler compiler = (JavaCompiler)Class.forName("com.sun.tools.javac.api.JavacTool").newInstance();

这在所有环境中都不是未来certificate或安全,但根据您的需要,它是一种选择。 如果其他人有更好的方法在自定义Ant任务中使用ToolProvider,请分享。

OSGi经常会出现此问题。 有些人提出了“桥类加载器”,例如参见本文 (可能只是桥接接口,而不是子类,所以也许你不能直接使用它)。

如果你想在“外来”对象上调用的方法很少,你也可以反思:

  javax.tools.CompilationTask task; task.getClass().getMethod("someMethodInTheSubclassThatICannotSee").invoke("a"); 

基于反思的想法,也许脚本语言也很有用(Groovy,Beanshell,JavaScript)。

简单的答案是,由两个不同的类加载器加载的同一个类是不同的类型,并且从不twain应该是可交叉分配的。 而已。 您必须让两个类使用相同的类加载器来获取共享类。

这通常是由于违反了先前将类加载推迟到ClassLoader父级的结果。 简单地说,任何类加载器必须首先要求它的父级在尝试加载它之前加载一个类。 否则会导致各种“有趣”的问题。

在你的具体例子中,由于A调用了B,B的类加载器无法委托给它的父类,因为如果A可以看到目标类,B的类加载器不需要加载它,因为A调用了B,因此是A的类加载器或其某些祖先加载B.

我遇到类似的问题我必须加载tools.jar当我发现子类没有加载时。 此链接中的详细信息https://stackoverflow.com/questions/14619179/webappclassloader-loadclass-cannot-find-class-at-runtime正如我所提到的,这可能不是一个好的解决方案,因为我们正在尝试修改类加载程序。 在这里发现了一些有用的注释http://easternlights-wisdomtree.blogspot.in/2013/02/classloading-blues-part1.html