使用自定义类加载器中的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.JavaCompiler
由URLClassLoader
加载,代理到系统类加载器
稍后, 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