Reputation: 6365
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(){...}".
Upvotes: 2
Views: 1591
Reputation: 6365
I ended up using Bean Shell. It's not perfect, but it solved 99% of the issue.
Upvotes: 0
Reputation: 28865
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.
Upvotes: 0
Reputation: 1431
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.
Upvotes: 0
Reputation: 1541
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.
Upvotes: 2
Reputation: 61526
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();
}
}
Upvotes: 0