Resolving classes from (complicated) runtime class loaders (compiling code ad hoc to run)
Compl Yue Still
complystill at gmail.com
Sat Nov 8 18:40:52 PST 2008
Hi Gentlemen,
Here comes an issue regarding needs for compiling java code to be run
within current JVM context (see http://sjsh.dev.java.net for concrete).
It works like a charm when running inside a normal (meaning no
complicated class loading scheme) JavaSE application, prompt the user
for some java statements, compile them into bytecode/class file, then
load it as a class and invoke its methods. however problems appear
when run from a more complex environment, like inside a app server,
Servlet container or RCP etc, where the depended class libraries are
not loaded by Launcher$AppClassLoader, javax.tools.JavaCompiler just
can't resolve classes loaded by a Servlet context loader and alikes.
After some investigation, I finally figured out that javac expects all
depended .class files be listed out by javax.tools.JavaFileManager,
ahead of type resolution. This is pretty okay for the command line
tool `javac', but when there comes needs for compilation and execution
of Java code ad hoc for currently running jvm context, by invoking
javax.tools.JavaCompiler, it just make things way too difficult. My
previous effort had worked out some ways to guess the -cp parameter to
be passed to JavaCompiler tool to workaround this issue, but so far
limited to URLClassLoader and Apache Tomcat loaders, and hardly for
Eclipse RCP. Obviously this solution can NOT `run anywhere'.
I believe there have been, and will be more and more projects/
components leveraging javax.tools.JavaCompiler as it became standard,
and they are to face the same situation. And by far I find a simpler
solution, by hacking a single javac's source file: src/share/classes/
com/sun/tools/javac/jvm/ClassReader.java
/** Fill in definition of class `c' from corresponding class or
* source file.
*/
private void fillIn(ClassSymbol c) {
if (completionFailureName == c.fullname) {
throw new CompletionFailure(c, "user-selected completion
failure by class name");
}
currentOwner = c;
JavaFileObject classfile = c.classfile;
+ // Added code to resolve classes from runtime class loaders {
+ if(classfile == null) {
+ try {
+ classfile = this.fileManager.getJavaFileForInput(
+ CLASS_PATH,
+ c.fullname.toString(),
+ JavaFileObject.Kind.CLASS);
+ } catch (IOException e) {
+ }
+ }
+ // Added code to resolve classes from runtime class loaders }
if (classfile != null) {
JavaFileObject previousClassFile = currentClassFile;
try {
.....
This works for me, but I hate the idea to distribute nonstandard
versions of javac.jar to users. But I'm not an openjdk dev guy,
neither knowledge nor time to get it pass jtreg and submitted to repo.
Can anybody here evaluate this patch for appropriateness and get it
upstream? I have examined the tools doc for javac and made sure the
resolved is not a documented feature or behavior, so should has no
spec impact.
Thanks for reading.
All the best,
Compl
More information about the compiler-dev
mailing list