2

Is there a way to compile and load a Java class during runtime without creating and storing a file in an operating system filesystem?

Say I have a database record that contains the string representation of a java class. I pull that string into Java memory. My goal is to compile that String into a java class and then load that class.

Let me make this clear. I want nothing to do with .java files or .class files, in any operating system.

Is this possible? And how?

For instance, here is code to load a Groovy class at runtime, and invoke a method:

ClassLoader parent = getClass().getClassLoader();
GroovyClassLoader loader = new GroovyClassLoader(parent);
Class groovyClass = loader.parseClass(new File("src/test/groovy/script/HelloWorld.groovy"));

// let's call some method on an instance
GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
Object[] args = {};
groovyObject.invokeMethod("run", args);

but could we do something like:

    ClassLoader parent = getClass().getClassLoader();
    GroovyClassLoader loader = new GroovyClassLoader(parent);
    Class groovyClass = loader.parseClass(new String("public class GroovyClass{}"));

?

Alexander Mills
  • 90,741
  • 139
  • 482
  • 817
  • 1
    I don't know anything about answer but curious about use case. What problem are you trying to solve by this. – RandomQuestion Sep 23 '13 at 23:55
  • Here is the problem: I am creating a database management studio for an object database (using db4o). Say the user of the studio wants to switch databases. With an Object database, the java classes ARE the representation of the tables/schemas/etc. So when you switch databases, you have to dynamically load the new java classes into memory, because those classes are necessary to describe the database. Say the user wants to add a new record. They need to call Class.newInstance() on a particular AND existing Java class that is already loaded in to the JVM. – Alexander Mills Sep 23 '13 at 23:58
  • 1
    Answering this with code might be really long, but here's my reference when I had the same case. [In-memory compilation](http://www.javablogging.com/dynamic-in-memory-compilation/). – Gx.Zero Sep 24 '13 at 00:03
  • 1
    When you say String representation, you mean like UTF-8 source, or a base64 encoded representation of the bytecode? – Dev Sep 24 '13 at 00:41
  • @Dev more likely utf-8 source code, but I guess I could store the compiled bytecode instead. Basically I could compile it first and store the .class file data in the DB or just store the source code first and compile later, I don't think that matters that much for the problem I have at the moment, but might matter later, can't say yet, though. – Alexander Mills Sep 24 '13 at 03:06

2 Answers2

2

Yes, I have a library which does this called OpenHFT/Java-Runtime-Compiler which replaces essence jcf. There is also other librarires such as beanshell and groovy which support this, but I haven't used them myself.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
1

If you can store the bytecode you should be able to do something like what is shown in the Javadoc for ClassLoader. You simply override the findClass(String) method.

public MyClassLoader extends ClassLoader {

    public Class findClass(String name) {
        byte[] b = fetchClassFromDB(String name);
        return defineClass(name, b, 0, b.length);
    }

    private byte[] fetchClassFromDB(String name) {
         /* Look up class in your database and return it as a byte array. */
    }

}
Dev
  • 11,919
  • 3
  • 40
  • 53