Create a java source dynamically, compile and callTag(s): Language


Java 1.6
Java 1.6 provides ToolProvider.getSystemJavaCompiler() to get a JavaCompiler implementation.

This example creates an Hello class source, compiles it and calls a given method.

import java.io.*;
import java.lang.reflect.Method;
import java.util.Arrays;

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;

public class DynamicCompilation {

  public static void main(String[] args) throws Exception {
    // create the source
    File sourceFile   = new File("/temp/Hello.java");
    FileWriter writer = new FileWriter(sourceFile);

    writer.write(
            "public class Hello{ \n" +
            " public void doit() { \n" +
            "   System.out.println(\"Hello world\") ;\n" +
            " }\n" +
            "}"
    );
    writer.close();

    JavaCompiler compiler    = ToolProvider.getSystemJavaCompiler();
    StandardJavaFileManager fileManager =
        compiler.getStandardFileManager(null, null, null);

    fileManager.setLocation(StandardLocation.CLASS_OUTPUT,
                            Arrays.asList(new File("/temp")));
    // Compile the file
    compiler.getTask(null,
               fileManager,
               null,
               null,
               null,
               fileManager.getJavaFileObjectsFromFiles(Arrays.asList(sourceFile)))
            .call();
    fileManager.close();


    // delete the source file
    // sourceFile.deleteOnExit();

    runIt();
  }

  @SuppressWarnings("unchecked")
  public static void runIt() {
    try {
      Class params[] = {};
      Object paramsObj[] = {};
      Class thisClass = Class.forName("Hello");
      Object iClass = thisClass.newInstance();
      Method thisMethod = thisClass.getDeclaredMethod("doit", params);
      thisMethod.invoke(iClass, paramsObj);
      }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}
  • The tools.jar (located in the [JDK1.6]\lib) must be in the classpath during runtime, it is not included with the JRE.
  • You can compile many sources in one shot.
  • The directory used to store the resulting class must be in the classpath if you want to use compiled class. In Eclipse, you add the directory in the Build Path (as an External Class Folder).
    Java 1.5 or less
    import java.io.*;
    import java.util.*;
    import java.lang.reflect.*;
    
    public class MakeTodayClass {
      Date today = new Date();
      String todayMillis = Long.toString(today.getTime());
      String todayClass = "z_" + todayMillis;
      String todaySource = todayClass + ".java";
    
      public static void main (String args[]){
        MakeTodayClass mtc = new MakeTodayClass();
        mtc.createIt();
        if (mtc.compileIt()) {
           System.out.println("Running " + mtc.todayClass + ":\n\n");
           mtc.runIt();
        }
        else {
           System.out.println(mtc.todaySource + " is bad.");
        }
      }
    
      public void createIt() {
        try {
          FileWriter aWriter = new FileWriter(todaySource, true);
          aWriter.write("public class "+ todayClass + "{");
          aWriter.write(" public void doit() {");
          aWriter.write(" System.out.println(\""+todayMillis+"\");");
          aWriter.write(" }}\n");
          aWriter.flush();
          aWriter.close();
        }
        catch(Exception e){
          e.printStackTrace();
        }
      }
    
      public boolean compileIt() {
        String [] source = { new String(todaySource)};
        ByteArrayOutputStream baos= new ByteArrayOutputStream();
    
        new sun.tools.javac.Main(baos,source[0]).compile(source);
        // if using JDK >= 1.3 then use
        //   public static int com.sun.tools.javac.Main.compile(source);    
        return (baos.toString().indexOf("error")==-1);
      }
    
      public void runIt() {
        try {
          Class params[] = {};
          Object paramsObj[] = {};
          Class thisClass = Class.forName(todayClass);
          Object iClass = thisClass.newInstance();
          Method thisMethod = thisClass.getDeclaredMethod("doit", params);
          thisMethod.invoke(iClass, paramsObj);
        }
        catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
    

    blog comments powered by Disqus