Compile Java code from Java application dynamically

Recently, I came across this problem of adding a scripting interface to an application that we were developing as a part of our term project. Let me describe more details about the project and the problem. The project that we were working on is all about generating Random Graphs and their analysis. A little research for libraries that would simplify our task yeilded an open source gem JUNG. As this post is neither about JUNG nor opensource I would try to talk as little as possible about their coolness. Some serious effort for a couple of days from my beloved friend Praveen resulted in this java beast.

The app has more tools for network analysis than this simple visualization like plotting the Degree Distribution Vs Rank, Pk Vs k, Clustering Coefficient Vs Rank, Betweenness centrality Vs Rank plots. Despite this much effort we are not confident about getting the best possible grade due to the lack of good innovation 🙂 ( I guess I am talking big here). So, here comes the small innovation. The networks that we analyse are generated using standard models like Barabási–Albert (BA) model, Erdős–Rényi model etc. In this way the application is limited and finds little use as these models had been analysed fully in every possible angle. So the application needs to support new models. But, writing code for each and every model is too complex and inefficient. The obvious path then would be to somehow express a network. The simplest way for the end user would be to express the network in english🙂. But poor computers yet donot understand english completely. So, the alternative is to ask the user to express the network in a language that computers can understand. The essence is that we need a scripting interface to express the network in our application. A single problem can have more than one solution and with opensource its more true. After all opensource is about choice. We had a couple of alternatives for this problem too. There are lots of embeddable scripting languages at our disposal.

We finally decided to pick java for this purpose. The solution that we picked might seem odd as it comes second to last in the scriptometer rankings. But, it has its own benefits. The obvious thing is the simplicity and elegance of the soultion.

  1. There is no need for us to learn a new language
  2. There are no integration costs. ( If you have missed the point, we programmed the whole application in java itself )

Once we have decided that the end user expresses the network in java, we need to chalk out a solution for running his network model to generate the set of vertices and edge. The problem boils down to two things

  1. Compile the code that he has written from the application itself.
  2. Execute his code to generate the network graph.

So how do you compile java code from java application. There are two solutions to this problem too. The first one is using an undocumented java class com.sun.tools.javac.Main. The other solution is to use a more standard and documented api available from java 1.6 onwards. We chose the earlier one as the final application has to run on a machine with only java 1.5, though that means using undocumented and unsupported functions. Time for some real java

String[] optionsAndSources = {“Synthesis.java”};

try{
PrintWriter out = new PrintWriter( new FileWriter( “C:\\out.txt” ) );
int status = Main.compile( optionsAndSources, out );
System.out.println( “status: ” + status );

} catch(IOException e){
System.err.println(“The file cannot be opened “+e);
}

Remeber to include the tools.jar shipped with the jdk in the classpath. Main.compile is basically a wrapper over the javac ( javac is not required on the machine running this application. ). It does the real job of compiling the java source code and producing the class file. The arguments are self explanatory.

Once the class file is generated it has to be executed. This process is much simpler and doesnt require any undocumented classes ( aah releif !! ). Java has a class called Class. Instances of the class Class represent classes and interfaces in a running Java application. One can create a new instance of any class using the member function newInstance(). Once a new instance is created it has to be typecasted into a class that the compiler knows at compile time so that we can invoke its methods. So we have an abstract base class called Model that models all network models. Any network model defined by the user inherits this base class and also implements an abstract function defined in the base class Network called generate. Once a new instance of the user’s network model is created, it is typecasted to the base class Network and the generate method is called on this object to generate the network. More code follows …

Model obj=null;
try {
Class c = Class.forName(“UserModel”);
obj = (Model)(c.newInstance());
} catch (Exception e) {
/* Catching Exception for simplicity. */
System.err.println(“error while loading class”+e);
}
obj.instantiate();
obj.compute();

I would try to write more about creating an applet from this application and may be a link to the applet that we created in my next blog.

5 responses to this post.

  1. Posted by Daniel on September 4, 2008 at 3:28 am

    Hey I’m writing a program with a friend of mine and we need something similar to this kind of “run-time compiling” but a) I can’t quite figure out how to implement your undocumented and supported method and b) I can run 1.6 and would like to know the approach to take with that route. If you need any more contextual information please let me know. Thanks.

    Reply

  2. Posted by raghuramn on September 9, 2008 at 4:51 pm

    Main.Compile method is available in com.sun.tools.javac package. Look out for that package. Java 1.6 has a cool feature called java compiler api. http://www.javabeat.net/articles/73-the-java-60-compiler-api-1.html
    you can find more articles through a simple search for “java compiler api”

    Reply

  3. Posted by sandy on January 7, 2013 at 1:00 pm

    Some of JDK classes are automatically loaded into JVM memory which can be seen by using the verbose options

    Reply

  4. Well java application has always been like this. when i first started working on java i thought its integration with our languages is the most toughest of all. later when i started earning and looking into all the codes very closely . i understood the concept and its importance in the world of programming. its is the backbond source code.

    Reply

  5. Posted by Ramesh on February 7, 2013 at 8:34 am

    Can any one tel me that Model datatype is mentioned in that code i am getting error if i used . Please tel me the Import statement Jar package. Which jar contains this Model.

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: