Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using javax.tools.ToolProvider from a custom classloader?

It seems to be impossible to use javax.tools.ToolProvider from a custom classloader as required by Ant or Webstart: http://bugs.sun.com/view_bug.do?bug_id=6548428

javax.tools.ToolProvider.getSystemJavaCompiler() loads javax.tools.JavaCompiler into a URLClassLoader whose parent is the system classloader. The API does not seem to allow users to specify a parent classloader.

How can one use javax.tools.JavaCompiler from a custom classloader?

For example:

  • Ant loads MyParserTask
  • MyParserTask parses Java source-code
  • MyParserTask is loaded by AntClassLoader that delegates to the system classloader
  • javax.tools.JavaCompiler is loaded by URLClassLoader thast delegates to the system classloader

At a later point, MyParserTask invokes:

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
  • Seeing how the two classes reside on separate classloaders, there doesn't seem to be a way for MyParserTask to interact with JavacTask without getting ClassCastException errors.

Any ideas?

like image 265
Gili Avatar asked Feb 23 '10 02:02

Gili


1 Answers

I had exactly the same problem. I'm using a custom ant task to scan the AST for certain kinds of method invocations. My solution, which may not be appropriate for you, was to instantiate the compiler myself instead of using the ToolProvider.

I replaced

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

with

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

This certainly isn't future proof or safe in all environments, but it is an option depending on your needs. If someone else has a better way around using ToolProvider in custom Ant tasks please share.

like image 148
user1980317 Avatar answered Sep 20 '22 09:09

user1980317