Question

I want to revisit an old question of mine about in-memory "compilation" of classes. Since about 1/2 a year have passed since I asked (and was somewhat answered), I'd like to re-raise the issue and see if something new would come up (so no, I don't consider this a duplicate).

The old question can be found here: On-the-fly, in-memory java code compilation for Java 5 and Java 6 - I suggest reading it (and the answers) before answering this question.

I'm quite content with beanshell doing the heavy work of evaluating string of a java class to an actual Class object. However, beanshell has been standing on version 2.0b4 for ages now and its limitations (no constructor, not even default; no generics, no for-each, no enums...) are annoying.

Reminder - this is to be used as a debugging interface, so performance considerations are negligible. However, I can't have server restarts, can't send class files to the location and JSPs are a very bad choice for me (I won't go into reasons here). Also, the end product must be a Class (or an Object of that class) so I could pass it around.

Some limitations: I can't have a JDK, so no javax.tools.JavaCompiler. I can't have JSPs since I don't have tomcat or other "real" web container. Java 5 syntax support would be great, especially generics, enums and parameterization. Support for default constructors would be very nice.

Any ideas?

Edit 1: I just found out that there is a round-about way of having constructors in beanshell - however you have to declare them "public void XXX(){...}" instead of the usual way "public XXX(){...}".

Was it helpful?

Solution 5

I ended up using Bean Shell. It's not perfect, but it solved 99% of the issue.

OTHER TIPS

If you can't bundle the SUN JDK tools.jar due to licensing reasons, perhaps you could include the Eclipse JDT Core compiler instead, see

http://help.eclipse.org/galileo/index.jsp?topic=/org.eclipse.jdt.doc.isv/guide/jdt_api_compile.htm

This is e.g. what the Jetty web server's JSP implementation does.

Can't you just copy over to tools.jar and get the javax.tools.JavaCompiler and add it to the classpath? Or is it a licensing issue.

This code, and tools.jar on the classpath, seems to work:

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;


public class Main
{
    public static void main(final String[] argv)
        throws IOException
    {
        final File[]                             files;
        final JavaCompiler                       compiler;
        final StandardJavaFileManager            fileManager;
        final Iterable<? extends JavaFileObject> compilationUnits;

        files = new File[]
        {
            new File(argv[0]),
        };        
        compiler         = ToolProvider.getSystemJavaCompiler();
        fileManager      = compiler.getStandardFileManager(null, null, null);
        compilationUnits = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(files));

        compiler.getTask(null, fileManager, null, null, null, compilationUnits).call();
        fileManager.close();
    }
}

I remember reading about the Bytecode Engineering Library (BCEL) a long time ago, back when Java 1.4 was all the rage. See http://jakarta.apache.org/bcel/index.html. I never used it, so I only mention it because it seems close to what you are asking about (and it works, or at least worked, with older VMs) and I didn't see anybody mention it yet.

Is there a specific reason why it has to be a Java string that produces the class/object? My spontaneous reaction is that JRuby is what you're looking for - it seems to be a very solid platform, and Ruby has a strong tradition of meta-programming.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top