【问题标题】:Using javax.tools.ToolProvider from a custom classloader?从自定义类加载器中使用 javax.tools.ToolProvider?
【发布时间】:2011-01-19 22:02:55
【问题描述】:

似乎无法按照 Ant 或 Webstart 的要求从自定义类加载器中使用 javax.tools.ToolProviderhttp://bugs.sun.com/view_bug.do?bug_id=6548428

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

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

例如:

  • Ant 加载 MyParserTask
  • MyParserTask 解析 Java 源代码
  • MyParserTask 由委托给系统类加载器的 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
  • 看到这两个类如何驻留在不同的类加载器上,MyParserTask 似乎无法与JavacTask 交互而不会出现ClassCastException 错误。

有什么想法吗?

【问题讨论】:

    标签: java compiler-construction casting classloader


    【解决方案1】:

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

    我换了

    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

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

    这当然不是面向未来或在所有环境中都是安全的,但它是一个取决于您的需求的选项。如果其他人在自定义 Ant 任务中使用 ToolProvider 有更好的方法,请分享。

    【讨论】:

      【解决方案2】:

      这个问题经常发生在 OSGi 中。有些人提出了“桥接类加载器”,例如this article(它可能只桥接接口,而不是子类,所以也许你不能直接使用它)。

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

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

      基于反射的想法,也许脚本语言也有帮助(Groovy、Beanshell、JavaScript)。

      【讨论】:

        【解决方案3】:

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

        这通常是由于违反了将类加载到 ClassLoader 的父级的先发制人的延迟。简单地说,任何类加载器必须首先要求它的父类加载一个类,然后再尝试自己加载它。否则会导致各种“有趣”的问题。

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

        【讨论】:

        • 我重写了问题以专注于 CompilationTask。请看一看。
        【解决方案4】:

        我遇到了类似的问题,当我发现没有加载子类时,我不得不加载 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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-11-08
          • 1970-01-01
          • 2023-03-07
          • 1970-01-01
          • 1970-01-01
          • 2012-09-06
          相关资源
          最近更新 更多