This question already has an answer here:
I'm using the JavaCompiler from the javax.tools package (JDK 1.7) to compile some stuff on the fly, like this:
compiler.run(null, null, "-cp", paths, "path/to/my/file.java");
It works but I would like to do it all in memory (e.g. pass a string with the code, not the source file, and get the byte code back not a .class file). I found that extending the InputStream
and OutputStream
parameters is no use since it's probably just the same as in the console. Do you know a way to make the run method work like this? Or do you know a confirmed way to do this with the getTask()
method? (extending the FileManager looks easy but isn't that easy :)
I wanted:
You can try it first here: http://ideone.com/cu1GhE#view_edit_box
The following code is based on Rekha Kumari code:
Main.java
DynamicCompiler.java
I wrote a library to do this a few years ago. It takes a String which can contain nested classes, compiles them and optionally loads them into the current class loader (so you don't need an additional class loader) If the JVM is running in debug mode it will write the generated code to a file so you can step through your generated code.
http://vanillajava.blogspot.co.uk/2010_11_01_archive.html
To paraphrase the example from
erolagnab
you can doUpdate, the source is available here https://github.com/OpenHFT/Java-Runtime-Compiler
And you can obtain the latest build via maven http://search.maven.org/#browse%7C842970587
A longer example.
This is a class that compiles entirely in memory.
I've taken (almost) the entirety of this from http://javapracs.blogspot.de/2011/06/dynamic-in-memory-compilation-using.html by Rekha Kumari (June 2011). Though this version is more than 100 lines shorter and has considerably more features (but no docs:P).
It can compile multiple classes at once, which is the only way to compile classes that depend on each other. If you wonder about the class "CompilerFeedback": I was working on a tiny Java IDE for coding-games where I needed that. I'm including it here because I assume that you want to do something with this compiler, and the predigestion might help with that. (I realize that some of the code in the CompilerFeedback class is complete crap. It was recycled from a years old attempt.
There's also a utility method, not needed for compilation, that derives the full class name from a class' source code (incl. package name, if it's provided). Very useful for calling the compiler, which does need this information.
DEMO CLASS:
COMPILER CLASS:
COMPILERFEEDBACK CLASS:
UTILITY METHOD (Not needed for the three classes further up.):
I think this here might be of help it basically shows how to compile Java source from memory (the string is located in the class).
It uses the
PrinterWriter
andStringWriter
to write the source to aString
/in memory and then uses theJavaCompiler
class (since JDK 6) to compile and run the program:If you have a look at the reference link you will find a few more other examples too
Reference:
I'd like to introduce my solution which runs well in production.
Here are the three source code files.
MemoryJavaCompiler.java
MemoryJavaFileManager.java
MemoryClassLoader.java
Explanations:
StringInputBuffer
class in theMemoryJavaFileManager.java
..class
files in memory, I implemented a classMemoryJavaFileManager
. The main idea is to override the functiongetJavaFileForOutput()
to store bytecodes into a map.MemoryClassLoader
, which reads bytecodes in the map and turn them into classes.Here is a unite test.
Reference