Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从自定义类加载器使用javax.tools.ToolProvider?_Java_Compiler Construction_Casting_Classloader - Fatal编程技术网

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

从自定义类加载器使用javax.tools.ToolProvider?,java,compiler-construction,casting,classloader,Java,Compiler Construction,Casting,Classloader,根据Ant或Webstart的要求,似乎不可能从自定义类加载器中使用javax.tools.ToolProvider: javax.tools.ToolProvider.getSystemJavaCompiler()将javax.tools.JavaCompiler加载到URLClassLoader中,该URLClassLoader的父级是系统类加载器。API似乎不允许用户指定父类加载器 如何使用自定义类加载器中的javax.tools.JavaCompiler 例如: Ant加载MyPars

根据Ant或Webstart的要求,似乎不可能从自定义类加载器中使用
javax.tools.ToolProvider

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

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

例如:

  • Ant加载MyParserTask
  • MyParserTask
    解析Java源代码
  • MyParserTask
    由委托给系统类加载器的
    AntClassLoader
    加载
  • javax.tools.JavaCompiler
    URLClassLoader
    thast委托给系统类加载器加载
稍后,
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
  • 看到这两个类如何驻留在不同的类加载器上,似乎没有办法让
    MyParserTask
    JavacTask
    交互,而不会出现
    ClassCastException
    错误

有什么想法吗?

OSGi经常出现这个问题。一些人提出了“桥类加载器”,例如(它可能只桥接接口,而不是子类,所以可能无法直接使用它)

如果您只想在“外来”对象上调用几个方法,您也可以不使用反射:

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

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

简单的答案是,由两个不同的类加载器加载的同一个类是不同的类型,而这两个类永远不能交叉分配。就这样。您必须让两个类使用相同的类加载器来获取共享类

这通常是由于违反了类装入器的父级对类装入的先发制人延迟。简单地说,任何类加载器都必须在尝试自己加载类之前首先要求其父级加载类。否则会导致各种“有趣”的问题


在您的特定示例中,由于A调用了B,B的类加载器未能委托给它的父类,因为如果A可以看到目标类,B的类加载器不需要加载它,因为A调用了B,因此A的类加载器或其某个祖先加载了B。

我也遇到了完全相同的问题。我正在使用一个定制的ant任务来扫描AST以查找特定类型的方法调用。我的解决方案可能不适合您,是自己实例化编译器,而不是使用ToolProvider

我换了

JavaCompiler compiler=ToolProvider.getSystemJavaCompiler()

JavaCompiler编译器=(JavaCompiler)Class.forName(“com.sun.tools.javac.api.JavacTool”).newInstance()


这当然不是在所有环境中都是经得起未来考验或安全的,但它是一个根据您的需要而定的选项。如果其他人有更好的方法在自定义Ant任务中使用ToolProvider,请与我们分享。

我也遇到过类似的问题,当我发现没有加载子类时,我不得不加载tools.jar。此链接中的详细信息 正如我提到的,这可能不是一个好的解决方案,因为我们正试图通过一个程序修补类加载。发现这里的一些注释也很有用

我重写了这个问题,把重点放在编译任务上。请看一看。