Estoy tratando de usar la API del compilador de Java para compilar alguna clase de Java. Esa clase importa algunos paquetes de los archivos jar que pueden cargarse por el contexto ClassLoader, llamémosle X, que NO es el cargador de clases del sistema. Cuando ejecuto la compilación, el compilador se queja de no reconocer las importaciones. Intenté especificar FileManager para pasar el cargador de clases, pero no ayuda.compilador de Java API ClassLoader
Cuando se llama al método de compilación, imprime primero "CLASE CARGADA", por lo que el contexto ClassLoader PUEDE encontrar la clase de dependencia. Sin embargo, la compilación falla (obtengo el mensaje "Compilación FALLIDA") y durante la compilación recibo errores como este:
/path/to/my/Source.java:3: package my.dependency no existe importar my.dependency.MyClass; ^
¿Qué estoy haciendo mal? ¿Cuál es la forma correcta de pasar el cargador de clases personalizado a compilationTask? No puedo extraer las URL de ClassLoader porque no es URLClassLoader.
Mis métodos son aquí:
public void compile(List<File> filesToCompile) {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager stdFileManager =
compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> fileObjects = stdFileManager
.getJavaFileObjectsFromFiles(filesToCompile);
FileManagerImpl fileManager = new FileManagerImpl(stdFileManager);
CompilationTask task = compiler.getTask(null, fileManager, null, null, null, fileObjects);
Boolean result = task.call();
if (result == true) {
System.out.println("Compilation has succeeded");
} else {
System.out.println("Compilation FAILED");
}
}
private final class FileManagerImpl extends ForwardingJavaFileManager<JavaFileManager> {
public FileManagerImpl(JavaFileManager fileManager) {
super(fileManager);
}
@Override
public ClassLoader getClassLoader(JavaFileManager.Location location) {
ClassLoader def = getContextClassLoader();
try {
def.loadClass("my.dependency.MyClass");
System.out.println("CLASS LOADED");
} catch (ClassNotFoundException ex) {
System.out.println("NOT LOADED");
}
return def;
}
}
Muchas gracias, lo comprobaré. Sin embargo, ¿no hay alguna forma de establecer solo el ClassLoader existente? –
@Pavel S. - Lo dudo, ya que tiene sentido, para proporcionar a la herramienta de compilación un classpath que está separado del classpath de aplicación real. Imagine, tiene una versión de una clase cargada pero quiere usar otra para compilar las clases. Esto * requiere * separación de clase. –