views:

560

answers:

11

In Java, is it possible to create a class definition on the fly while an application is running, and then create an object of that class?

For example, a running application would read in a text file that contains a list of class members to include in the new class. The application would then define a class definition based on the list of members, and then insantiate it.

+1  A: 

You can do this by writing the code for your new class out to a file, then invoking the Java compiler on that file and using a classloader to dynamically load that class into your running application. Apache Tomcat does this for its JSP pages; it takes the code, makes some changes to it, wraps it in a try/catch block in the middle of a class, which it then writes to the filesystem, compiles it, and uses a classloader to get and sue it to serve requests.

Eli Courtwright
+7  A: 

Yes its possible to do so in theory your class file is byte code which is at the end a byte array! you can then use the method defineClass(String, byte[], int, int) to get a Class instance that can be used to instantiate objects via reflection.

In practice you can use something like CGLib or javaassist.

You can also use the long way of generating the java code in a file, invoking the compiler, then loading the file.

MahdeTo
+1  A: 

Sure it is possible. See for example this article.

kgiannakakis
+2  A: 

You can dynamically generate classes using ASM

Boune
A: 

Perhaps a little overkill, the Apache BCEL (Byte Code Engineering Library) can be used to create class files during runtime.

Although I haven't tried it myself, conceivably, one could then create a class, load it, and instantiate it during runtime.

coobird
A: 

Yes, that is possible.

You can create classes with Javassist at runtime by defining the body of the class and making javassist compile your new class.

Javassist has a custom compiler that creates bytecode based on the definition of your class. It has some particular ways to handle things, but it's very easy and intuitive to use this library.

Javassist is used on JBoss, and I think that is a good reference :)

The same can be achieved with BCEL, however it's much harder (but in this way you have more control over what is being generated).

Edison Gustavo Muenz
+1  A: 

You could probably do something like that with JRuby, or JPython or Groovy if you must.

If you're feeling particularly masochistic you could look at BCEL.

Evan
+1  A: 

If you want Java and metaprogramming, use Groovy.

Stefan Kendall
A: 

ASM is the lowest level bytecode library for Java, I suppose. That makes it very hard but also very powerful. I recommend reading ASM's documentation (PDF) to really understand how bytecode generation in Java works. That documentation also explains how to load the bytecode in the class loader (another hard topic to do right).

After that you may use one of the higher level libraries, if it makes your life easier, and understand what they do. For many cases, such as generating proxies, the CGLIB is useful and simple to use. For more power, many have mentioned Javassist (I haven't used it - CGLIB and ASM have been good for me).

Esko Luontola
+1  A: 

Perhaps the simplest solution (in terms of not requiring extra libraries) would be to use the Java compiler API that comes with Java 6. You just just be able to generate the .java, compile and then perform a Class.forName().

Brian Agnew
A: 

There was a recent question here regarding in-memory compilation which should give you some hints on what to do after you've managed to generate the source code.

Phil M