java compiler-construction casting classloader

¿Cómo usar javax.tools.ToolProvider desde un cargador de clases personalizado?



compiler-construction casting (4)

Parece imposible utilizar javax.tools.ToolProvider desde un cargador de clases personalizado como lo requieren Ant o Webstart: http://bugs.sun.com/view_bug.do?bug_id=6548428

javax.tools.ToolProvider.getSystemJavaCompiler() carga javax.tools.JavaCompiler en un URLClassLoader cuyo padre es el cargador de clases del sistema. La API no parece permitir a los usuarios especificar un cargador de clases principal.

¿Cómo se puede usar javax.tools.JavaCompiler desde un cargador de clases personalizado?

Por ejemplo:

  • Ant cargas MyParserTask
  • MyParserTask analiza el código fuente de Java
  • MyParserTask es cargado por AntClassLoader que delega en el cargador de clases del sistema
  • javax.tools.JavaCompiler es cargado por URLClassLoader y delegado en el cargador de clases del sistema

En un momento posterior, MyParserTask invoca:

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

  • Al ver cómo residen las dos clases en cargadores de clases separados, no parece haber una manera para que MyParserTask interactúe con JavacTask sin obtener errores ClassCastException .

¿Algunas ideas?


Estaba teniendo problemas similares. Tenía que cargar las herramientas. Jar Cuando descubrí que no se estaba cargando una subclase. detalles en este enlace https://.com/questions/14619179/webappclassloader-loadclass-cannot-find-class-at-runtime Como menciono, esta puede no ser una buena solución, ya que estamos tratando de jugar con la carga de clases a través de un programa. algunas notas aquí también son útiles http://easternlights-wisdomtree.blogspot.in/2013/02/classloading-blues-part1.html


Este problema ocurre frecuentemente con OSGi. Algunas personas han creado "cargadores de clase puente", consulte, por ejemplo, este artículo (que probablemente solo une interfaces, no subclases, por lo que quizás no pueda usarlo directamente).

Si solo hay unos pocos métodos que desea invocar en el objeto "extraño", también puede salirse con la suya:

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

Sobre la base de la idea de reflexión, tal vez también sea útil un lenguaje de scripts (Groovy, Beanshell, JavaScript).


La respuesta simple es que la misma clase cargada por dos cargadores de clases diferentes es un tipo diferente y nunca los dos serán asignables cruzadamente. Eso es. Debes tener ambas clases para usar el mismo cargador de clases para obtener la clase compartida.

Esto normalmente sería el resultado de la violación del aplazamiento preventivo de la carga de clase a un padre de ClassLoader. En pocas palabras, cualquier cargador de clases primero debe pedirle a su padre que cargue una clase antes de intentar cargarlo. Hacer lo contrario da lugar a todo tipo de problemas "interesantes".

En su ejemplo específico, dado que A invocó B, fue el cargador de clases de B que no pudo delegar en su padre, ya que si A puede ver la clase objetivo, el cargador de clases de B no necesitó cargarlo, dado que A invocó B y por lo tanto A cargador de clase o algún antecesor del mismo cargado B.


Tuve exactamente el mismo problema. Estoy usando una tarea ant personalizada para escanear el AST para ciertos tipos de invocaciones de métodos. Mi solución, que puede no ser adecuada para usted, fue crear una instancia del compilador en lugar de utilizar el ToolProvider.

Reemplacé

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

con

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

Esto ciertamente no es a prueba de futuro o seguro en todos los entornos, pero es una opción que depende de sus necesidades. Si alguien más tiene una mejor forma de utilizar el ToolProvider en las tareas Ant personalizadas, comparta.