ClassLoader Java Compiler API

I am trying to use the Java Compiler API to compile some java class. This class imports some packages from jar files that can be loaded with the ClassLoader context, let it call it, which is NOT a system loader. When I start compilation, the compiler complains about not recognizing the import. I tried to specify fileManager to pass the classloader, but that does not help.

When the compilation method is called, it first prints "CLASS LOADED", so the ClassLoader context can find the dependency class. However, the compilation itself fails (I get the message "Compiling FAILED"), and during compilation I get errors like this:

/path/to/my/Source.java data: package my.dependency does not exist import my.dependency.MyClass; ^

What am I doing wrong? What is the proper way to pass a custom classloader to compilationTask? I cannot extract the urls from ClassLoader, since this is not a URLClassLoader.

My methods are here:

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; } } 
+6
source share
3 answers

This question has an answer . You will need to set the class path through the list of options using the getTask() method (as detailed in the accepted answer).

0
source

The main thing is that when the class loader loads the classes, javac will call JavaFileManager#list() to get a list of all the files in the package.

Therefore, to use a custom classloader, you need to modify (or extend) it to override JavaFileManager#list() . We hope you can reuse some of the logic used to load classes.

You can use native JavaFileObject implementations to represent class objects. Then you need to override JavaFileManager#inferBinaryName() (otherwise a javac version error will be JavaFileManager#inferBinaryName() ). Your JavaFileObject implementations JavaFileObject also override (at least) JavaFileObject#openInputStream .

Here are a few pointers: http://atamur.blogspot.be/2009/10/using-built-in-javacompiler-with-custom.html

Also, don't make your life harder than you need, and extend the ForwardingJavaFileManager and SimpleJavaFileObject .

For reference, here is an example implementation:

  @Override public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException { Iterable<JavaFileObject> stdResults = fileManager.list(location, packageName, kinds, recurse); if (location != StandardLocation.CLASS_PATH || !kinds.contains(JavaFileObject.Kind.CLASS)) { return stdResults; } Set<JavaFileObject> additional = pkgObjects.get(packageName); if (additional == null || additional.isEmpty()) { return stdResults; } List<JavaFileObject> out = new ArrayList<>(); for (JavaFileObject obj : additional) { out.add(obj); } for (JavaFileObject obj : stdResults) { out.add(obj); } return out; } 

Where pkgObjects is a map from package names to JavaFileObject . The way you fill out this map depends on how your class loader works.

+3
source

To load a class from another jar file, you can try with the Reflection API, it's just ... go to the following link http://download.oracle.com/javase/tutorial/reflect/index.html ..

0
source

Source: https://habr.com/ru/post/886879/


All Articles