How to use JDK6 ToolProvider and JavaCompiler with class class loader?

My use case is to collect the generated source files from a java program using the ToolProvider and JavaCompiler classes provided in JDK 6. The source files contain class references in the class loader (it works in the J2EE container), but not in the system class loader. I understand that by default ToolProvider will create an instance of JavaCompiler with a system class loader.

Is there a way to specify a class loader to use JavaCompiler?

I tried this approach, modified from IBM DeveloperWorks:

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

with FileManagerImpl is defined as:

 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(); } } 

The column indicates that it is called only once during annotation processing. I checked the class specified in the source file to be compiled is not in the system class path, but is accessible from the class loader.

+6
java classloader javac java-compiler-api
source share
3 answers

If you know the path to the files that are known to the contextclassloader, you can pass them to the compiler:

  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(); 

This example assumes that you are using a URLClassloader (which allows you to get the classpath), but you can insert your own classpath if you want.

+8
source share

Another option is to use Commons JCI .

+1
source share

Here you ask two separate questions.

One of them is how to compile classes not found on the system path. This is easy to solve by passing the -classpath command line argument to the compiler (as Leihca first mentioned).

Secondly, how to create an instance of ToolProvider and JavaCompiler in a stream classloader. At the time of this writing, this is an unresolved question: Using javax.tools.ToolProvider from a custom classloader?

0
source share

All Articles