Resolving classes from (complicated) runtime class loaders (compiling code ad hoc to run)

Compl Yue Still complystill at
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 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, 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,  
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, 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 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/ 

     /** 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,

More information about the compiler-dev mailing list