Home of The JavaSpecialists' Newsletter

180Generating Static Proxy Classes - 1/2

Posted: 2010-02-19Category: PerformanceJava Version: 1.6+Dr. Heinz M. Kabutz

Abstract: In this newsletter, we have a look at how we can create new classes in memory and then inject them into any class loader. This will form the basis of a system to generate virtual proxies statically.


A hearty welcome to the 180th edition of The Java(tm) Specialists' Newsletter, sent from my balcony with a stunning view of the snow-capped "Lefka Ori" mountains. On my right is a view down to the Cretan sea. In front I see my neighbour's vineyard and lots of olive trees. The birds think it is spring already and are twittering to their hearts' content...

But please do not be jealous! As from May 2010, you will have an excuse to visit this historical island and do so as a tax write-off! We are now offering courses on Crete at our new conference facility with even better views than from my balcony. Here is what our typical day will look like: We will cover about 250 slides of advanced Java material per day, together with lots of practical exercises to apply your new knowledge. To obtain your JavaSpecialist.EU Certificate of Training (view a sample student report here), you have to complete the entire course, so no slacking will be tolerated! (Tell your boss that :-)

For lunch we will pop up to our favourite restaurant "Taverna Irene", where you will be served delicious traditional Cretan home-cooked food. Coffee time in the afternoons will be held at our pool with the opportunity for a quick dip to cool down. Included in the price is a dinner at the Kalathas Beach Restaurant and a spit roast at my house on the last evening. On other evenings we can go for a stroll through the olive groves and past the watermelon fields down to Tersanas beach for a swim and perhaps a drink or two.

As always, if Crete does not suit you, we also have excellent training partners in Canada, USA, France, Germany and Norway through whom we offer the exact same training as on the island of Crete. Plus, for larger groups we can do in-house courses at your company.

NEW: Refactoring to Java 8 Lambdas and Streams Workshop Are you currently using Java 6 or 7 and would like to see how Java 8 can improve your code base? Are you tired of courses that teach you a whole bunch of techniques that you cannot apply in your world? Check out our one day intensive Refactoring to Java 8 Lambdas and Streams Workshop.

Generating Static Proxy Classes - 1/2

Since the code for building the proxy class generator is quite long, I have split the newsletter into several parts. The next issue will probably be sent in ten days from Düsseldorf.

A few weeks ago, we were talking about dynamic proxies at my Java Specialist Master Course in Baltimore, MD. I told my students that generated code would be much faster and that you could do this from within Java. I had known about the javax.tools.JavaCompiler class for a number of years, but had not managed to use it to my satisfaction. I figured out how to compile classes from strings, but the resulting class files were dumped on the disk instead of being loaded into the current class loader.

After much searching and head scratching, I found a website that described how to do this in Groovy, using the JavaCompiler. The key was the ForwardingJavaFileManager class. This led to another excellent article called Dynamic In-memory Compilation. Both articles showed how to convert a String into a byte[] representing the Java class.

Once we have obtained the byte[], we need to turn this into a class. One easy solution is to make a ClassLoader that inherits from our current one. One of the risks is that we then enter ClassLoader hell. I wanted to rather take the dynamic proxy approach, which lets the user specify into which ClassLoader we want our class to be injected. In my solution I use the same mechanism by calling the private static Proxy.defineClass0() method. We could probably also have used the public Unsafe.defineClass() method, but both "solutions" bind us to an implementation of the JDK and are thus not ideal.

In this newsletter, we look at how the Generator works. It uses a GeneratedJavaSourceFile to store the String, in this case actually a CharSequence. The CharSequence interface is implemented by String, StringBuffer and StringBuilder, thus we do not need to create an unnecessary String. We can simply pass in our existing StringBuilder. I wish more classes used the CharSequence interface!

According to the JavaDocs, the recommended URI for a Java source String object is "string:///NameOfClass.java", but "NameOfClass.java" also works, so that is what we will use.

import javax.tools.*;
import java.io.*;
import java.net.*;

class GeneratedJavaSourceFile extends SimpleJavaFileObject {
  private CharSequence javaSource;

  public GeneratedJavaSourceFile(String className,
                                 CharSequence javaSource) {
    super(URI.create(className + ".java"),
    this.javaSource = javaSource;

  public CharSequence getCharContent(boolean ignoreEncodeErrors)
      throws IOException {
    return javaSource;

The next class is used to hold the generated class file. It presents a ByteArrayOutputStream to the JavaFileManager in the openOutputStream() method. The URI here is not used, so I just specify "generated.class". Once the Java source is compiled, we extract the class with getClassAsBytes().

import javax.tools.*;
import java.io.*;
import java.net.*;

class GeneratedClassFile extends SimpleJavaFileObject {
  private final ByteArrayOutputStream outputStream =
      new ByteArrayOutputStream();

  public GeneratedClassFile() {
    super(URI.create("generated.class"), Kind.CLASS);

  public OutputStream openOutputStream() {
    return outputStream;

  public byte[] getClassAsBytes() {
    return outputStream.toByteArray();

The GeneratingJavaFileManager forces the JavaCompiler to use the GeneratedClassFile's output stream for writing the class:

import javax.tools.*;
import java.io.*;

class GeneratingJavaFileManager extends
    ForwardingJavaFileManager<JavaFileManager> {
  private final GeneratedClassFile gcf;

  public GeneratingJavaFileManager(
      StandardJavaFileManager sjfm,
      GeneratedClassFile gcf) {
    this.gcf = gcf;

  public JavaFileObject getJavaFileForOutput(
      Location location, String className,
      JavaFileObject.Kind kind, FileObject sibling)
      throws IOException {
    return gcf;

The Generator class uses the private static "defineClass0" method found in Proxy to add the class into the ClassLoader. This will cause an exception if the class already exists in that class loader. Another approach is to use a new ClassLoader. See the Dynamic In-memory Compilation article for an example of how to do that.

Compiling syntax errors will be printed to System.err. You should replace that code with calls to your favourite logging system.

import javax.tools.*;
import java.lang.reflect.*;
import java.util.*;

public class Generator {
  private static final Method defineClassMethod;
  private static final JavaCompiler jc;

  static {
    try {
      defineClassMethod = Proxy.class.getDeclaredMethod(
          "defineClass0", ClassLoader.class,
          String.class, byte[].class, int.class, int.class);
    } catch (NoSuchMethodException e) {
      throw new ExceptionInInitializerError(e);
    jc = ToolProvider.getSystemJavaCompiler();
    if (jc == null) {
      throw new UnsupportedOperationException(
          "Cannot find java compiler!  " +
              "Probably only JRE installed.");

  public static Class make(ClassLoader loader,
                           String className,
                           CharSequence javaSource) {
    GeneratedClassFile gcf = new GeneratedClassFile();

    DiagnosticCollector<JavaFileObject> dc =
        new DiagnosticCollector<JavaFileObject>();
    boolean result = compile(className, javaSource, gcf, dc);
    return processResults(loader, javaSource, gcf, dc, result);

  private static boolean compile(
      String className, CharSequence javaSource,
      GeneratedClassFile gcf,
      DiagnosticCollector<JavaFileObject> dc) {
    GeneratedJavaSourceFile gjsf = new GeneratedJavaSourceFile(
        className, javaSource
    GeneratingJavaFileManager fileManager =
        new GeneratingJavaFileManager(
            jc.getStandardFileManager(dc, null, null), gcf);
    JavaCompiler.CompilationTask task = jc.getTask(
        null, fileManager, dc, null, null, Arrays.asList(gjsf));
    return task.call();

  private static Class processResults(
      ClassLoader loader, CharSequence javaSource,
      GeneratedClassFile gcf, DiagnosticCollector<?> dc,
      boolean result) {
    if (result) {
      return createClass(loader, gcf);
    } else {
      // use your logging system of choice here
      System.err.println("Compile failed:");
      for (Diagnostic<?> d : dc.getDiagnostics()) {
      throw new IllegalArgumentException(
          "Could not create proxy - compile failed");

  private static Class createClass(
      ClassLoader loader, GeneratedClassFile gcf) {
    try {
      byte[] data = gcf.getClassAsBytes();
      return (Class) defineClassMethod.invoke(
          null, loader, null, data, 0, data.length);
    } catch (RuntimeException e) {
      throw e;
    } catch (Exception e) {
      throw new IllegalArgumentException("Proxy problem", e);

We can try this out by passing a String to the Generator. Here we produce a class that implements Runnable, called WatchThis. We then make an instance of the class and pass it to a thread to run.

public class GeneratorTest {
  public static void main(String[] args) throws Exception {
    Class testClass = Generator.make(
        null, "WatchThis",
        "" +
            "package coolthings;\n" +
            "\n" +
            "public class WatchThis implements Runnable {\n" +
            "  public WatchThis() {\n" +
            "    System.out.println(\"Hey this works!\");\n" +
            "  }\n" +
            "\n" +
            "  public void run() {\n" +
            "    System.out.println(Thread.currentThread());\n" +
            "    while(Math.random() < 0.95) {\n" +
            "      System.out.println(\"Cool stuff!\");\n" +
            "    }\n" +
            "  }\n" +
    Runnable r = (Runnable) testClass.newInstance();
    Class<? extends Runnable> clazz = r.getClass();
    System.out.println("Our class: " + clazz.getName());
    System.out.println("Classloader: " + clazz.getClassLoader());
    Thread t = new Thread(r, "Cool Thread");

Distributing Code

The JavaCompiler depends on the tools.jar file that is distributed with the JDK, but not with the JRE. It searches for it in all the usual install places. Thus your users either have to install the JDK or you need to distribute the tools.jar together with your application. See the README file in the JDK install directory for more information of what you may redistribute.

Additional Articles

After I completed my code, I found two more articles that would be of interest: Using built-in JavaCompiler with a custom classloader and Create dynamic applications with javax.tools

Kind regards



Related Articles

Browse the Newsletter Archive

About the Author


Java Champion, author of the Javaspecialists Newsletter, conference speaking regular... About Heinz

Java Training

We deliver relevant courses, by top Java developers to produce more resourceful and efficient programmers within their organisations.

Java Consulting

Nobody ever wants to call a Java performance consultant, but with first-hand experience repairing and improving commercial Java applications - JavaSpecialists are a good place to start...

Threading Emergency?

If your system is down, we will review it for 15 minutes and give you our findings for just 1 € without any obligation.