First of all what i try to achieve:
I want to compile java classes dynamically in-memory, during runtime. Basically with the provided Java Compiler API thats not really big of a deal, but when it comes to multiple classes per .java file I'm lost.
What i got so far:
I'm currently working with the InMemoryJavaCompiler
provided in an answer to this question (Compile code fully in memory with javax.tools.JavaCompiler)
As described above, the compilation of single classes per file is no problem, but I want to be able to compile pretty much any valid .java files.
For example the file (FileOne.java
) I try to compile looks like this:
package test;
public class FileOne {
public static void main(String args[]) {
System.out.println("Hello, World");
}
}
class Functions {
public static int test(int x) {
return -x;
}
}
When i try to compile this file like InMemoryJavaCompiler.compile("test.FileOne", source)
, I get an Exception marking the defineClass(...)
line in the overwritten ClassLoader that says:
java.lang.ClassFormatError: Extra bytes at the end of class file test/FileOne
This problem also exists with inner classes, but there it is only some kind of naming/calling problem, I guess:
java.lang.NoClassDefFoundError: test/FileOne (wrong name: test/FileOne$Functions)
Yes, you are right that
InMemoryJavaCompilation
as-is currently available on github does not work if a class has inner or anonymous classes. I have experienced exactly the same problem that you described.After a long searching I found JSCC which is very complete. Thanks to verhas (github user name) for developing it and making it available. I tested JSCC with nested classes and it works fine. You can find the code and how to use it on Github.
https://github.com/verhas/jscc
As far as I understood, the problem with
InMemoryJavaCompilation
is that it stores onebyte array
per class. However, compiler generates more than one classes for a class with nested classes or anonymous classes. In that case,InMemoryJavaCompilation
stores only the last class returned by the compiler, and that may not be the top level class. Therefore, you may getjava.lang.NoClassDefFoundError
. JSCC maintains aByte Array Map
to keep the compiled code of all the classes.Although you asked this question long time back, I hope this helps.