test help examples java javac classloader java-compiler-api

help - javac test java



¿Cómo uso JDK6 ToolProvider y JavaCompiler con el cargador de clases de contexto? (3)

Mi caso de uso es compilar archivos fuente generados de un programa java usando las clases ToolProvider y JavaCompiler provistas en JDK 6. Los archivos fuente contienen referencias a clases en el cargador de clases de contexto (se ejecuta en un contenedor J2EE), pero no en el cargador de clases del sistema. Tengo entendido que, de forma predeterminada, el Proveedor de herramientas creará la instancia de JavaCompiler con el cargador de clases del sistema.

¿Hay alguna forma de especificar un cargador de clases para JavaCompiler?

Intenté este enfoque, modificado a partir de algo en IBM DeveloperWorks:

FileManagerImpl fm = new FileManagerImpl(compiler.getStandardFileManager(null, null, null););

con FileManagerImpl definido como:

static final class FileManagerImpl extends ForwardingJavaFileManager<JavaFileManager> { public FileManagerImpl(JavaFileManager fileManager) { super(fileManager); } @Override public ClassLoader getClassLoader(JavaFileManager.Location location) { new Exception().printStackTrace(); return Thread.currentThread().getContextClassLoader(); } }

El stacktrace indica que solo se llama una vez durante el proceso de anotación. Verifiqué que la clase a la que se hace referencia en el archivo de origen que se compila no está en el classpath del sistema, pero está disponible desde el cargador de clases de contexto.



Si conoce la ruta de clase a los archivos que conoce el editor de clases de contexto, puede pasarlos al compilador:

StandardJavaFileManager fileManager = compiler.getStandardFileManager(this /* diagnosticlistener */, null, null); // get compilationunits from somewhere, for instance via fileManager.getJavaFileObjectsFromFiles(List<file> files) List<String> options = new ArrayList<String>(); options.add("-classpath"); StringBuilder sb = new StringBuilder(); URLClassLoader urlClassLoader = (URLClassLoader) Thread.currentThread().getContextClassLoader(); for (URL url : urlClassLoader.getURLs()) sb.append(url.getFile()).append(File.pathSeparator); options.add(sb.toString()); CompilationTask task = compiler.getTask(null, fileManager, this /* diagnosticlistener */, options, null, compilationUnits); task.call();

En este ejemplo, se supone que está utilizando un URLClassloader (que le permite recuperar la ruta de clases), pero puede insertar su propia ruta de clase si así lo desea.


Estás haciendo dos preguntas separadas aquí.

Una es cómo compilar las clases que no se encuentran en el classpath del sistema. Esto se resuelve fácilmente pasando el argumento de la línea de comando "-classpath" al compilador (como lo mencionó primero Leihca).

El segundo es cómo crear una instancia de ToolProvider y JavaCompiler en el cargador de clases de contexto del hilo. En el momento de escribir esto, esta es una pregunta sin resolver: ¿Cómo usar javax.tools.ToolProvider desde un cargador de clases personalizado?