5

I am generating a dynamic class in my java program by writing all my code into a java file, compiling the java file into a class file and then loading the class file with a URLClassLoader. The problem with this is that it creates a lot of files on my computer. Is their a way to do this with only creating "virtual files"(file objects) and not generating any actual files, because the way im doing it takes time and seems unclean and inefficient.

Josh Sobel
  • 1,268
  • 3
  • 14
  • 27
  • http://docs.oracle.com/javase/6/docs/api/javax/tools/JavaCompiler.html ? – Affe Mar 19 '13 at 23:55
  • but dont i still need to create the .java file so that i can compile it – Josh Sobel Mar 19 '13 at 23:58
  • see the JavaSourceFromString example for a possible solution in @Affe 's link. – Pyranja Mar 20 '13 at 00:00
  • there is no particular requirement that the implementation of javax.tools.JavaFileObject represent an actual file on disk, no, it can just be a wrapper around a string in memory. (sorry, don't mean to be obtuse, just too busy at the moment to write a full blown answer and thought maybe if we pointed you in the right direction you'd be able to find some tutorials around the web that will help you out.) – Affe Mar 20 '13 at 00:02
  • but when i load the class i need a class file to load it from – Josh Sobel Mar 20 '13 at 00:08

3 Answers3

1

If you look at the ClassLoader class, it has a method to define a class from the actual series of bytes.

Java docs for ClassLoader

I admit I have not worked with class loaders on this low of a level, but my understanding is that this is a template pattern, where the base ClassLoader class knows how to create a class in the VM based off raw byte code. Child classes are responsible for figuring out where to find the byte code for a given class.

So the solution for you may be to stop using URLClassLoader entirely and extend ClassLoader yourself.

Brandon
  • 9,822
  • 3
  • 27
  • 37
1

Byte code generation and manipulation libraries allow you to modify and generate classes on the fly, in memory. Javassist is probably easiest to start with since it permits using Java syntax.

They also tend to be lighter weight than entire standalone compilers.

Joni
  • 108,737
  • 14
  • 143
  • 193
0

A (more) straightforward solution would be to do the following:

  • Compile your class files into a common directory
  • Create a custom ClassLoader that extends ClassLoader
  • Use this ClassLoader to read in the .class files.

Here's something to get you started - I'll leave the exercise of getting the byte code into the object as an exercise to the reader. (It isn't very difficult if you use a bit of SimpleFileVisitor work in this. Check out Java.NIO.)

public class CustomClassLoader extends ClassLoader {

    @Override
    public Class findClass(String binaryClassName) {
        byte[] b = customLoadClassData(binaryClassName);
        return defineClass(binaryClassName, b, 0, b.length);
    }

    private byte[] customLoadClassData(String binaryClassName) {
        // Be sure to read in the specific .class file you want.
        // A tip is to handle this *outside* of this class.
    }

}

You can then use it like this:

CustomClassLoader loader = new CustomClassLoader();
Class clazz = loader.findClass("com.stackoverflow.some.binary.name");

...provided that it didn't throw an exception or come back null.

Makoto
  • 104,088
  • 27
  • 192
  • 230