The Artima Developer Community
Sponsored Link

Java Community News
Eamonn McManus on Dynamic Code Generation

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Frank Sommers

Posts: 2642
Nickname: fsommers
Registered: Jan, 2002

Eamonn McManus on Dynamic Code Generation Posted: Oct 19, 2006 12:03 PM
Reply to this message Reply
Summary
Eamonn McManus, Sun's JMX development lead, distinguishes between static and dynamic code generation, and demonstrates dynamic Java code generation in a recent blog post. While this technique is not the easiest way to produce Java code, McManus illustrates where dynamic bytecode generation can be useful.
Advertisement

Source code generation has received much attention lately, both as a productivity technique and as a way to ensure consistency. In a recent blog post, Build Your Own Interface - Dynamic Code Generation, Sun's JMX implementation lead Eamonn McManus discusses a much less talked-about angle of code generation: that of generating Java bytecode on the fly, without creating an intermediary source file.

McManus warns that:

The first thing to remember before launching into dynamic code generation is that it is nearly always a much better idea to use static code generation if you can. Static code generation just means writing code as .java files and compiling them with the Java compiler in the usual way. Dynamic code generation means creating code at run time that didn't exist when you compiled your program. Dynamically-created code can often only be run using reflection.

Why would you want to dynamically generate Java byte code? McManus points to an example where an API requires that you declare an interface for a class, and thus you need to create both the interface and an implementation at the same time. Without code generation, that would mean having to define two class files. McManus illustrates that requirement in JMX:

A Standard MBean is a Java class that implements ... the MBean interface. That interface determines which methods in the class are management methods. When you register an instance of the class with the JMX Agent (MBean Server), these methods can be called by a management client such as JConsole.

Here's an example of an MBean class and its accompanying interface:

public class Cache implements CacheMBean {
    public int getSize() {
    	return size;
    }

    public void setSize(int size) {
    	this.size = size;
    }

    public int getUsed() {
    	return used;
    }
    ...
}

public interface CacheMBean {
    public int getSize();
    public void setSize(int size);
    public int getUsed();
}

It can be troublesome to maintain two different source files, for the public class Cache and the public interface CacheMBean. We often hear people ask for the ability to specify the managed methods with an annotation instead. In other words, to get rid of CacheMBean and instead write Cache like this:

public class Cache {
    @Managed
    public int getSize() {
    	return size;
    }

    @Managed
    public void setSize(int size) {
    	this.size = size;
    }

    @Managed
    public int getUsed() {
    	return used;
    }
    ...
}

How might we implement that?

McManus illustrates model MBeans and writing an annotation processor as possible solutions, and then shows the more flexible alternative of generating Java bytecode for the interface:

So how do we go about generating the interface dynamically? There are at least three ways.

  • Write the Java source code to a file and invoke the Java compiler on that file. You might do this using Runtime.exec, for example. As of Java SE 6, you can use the javax.tools package to invoke the compiler...
  • Use a standard byte-code generation library, such as Apache BCEL. Pulling in the whole of BCEL just to generate an interface seems a bit like overkill, though.
  • Generate the byte code yourself. This is usually a major undertaking. But in fact most of the difficulty in generating byte code is involved in generating executable code. Interfaces don't contain any executable code, so it is not unreasonably difficult to generate the byte code for an interface.

The rest of the article shows how to populate a buffered stream with the bytecodes for the interface, and load that buffered stream as input to a classloader:

The main difficulty is that the class file is in two main parts, the constant pool, and "everything else". Everything else here is the class properties (such as its name and superclass) and the contained fields and methods. Every time there is a class name, string, or other constant in this second part, it is actually a reference to the constant pool...

When generating a class file, you are actually generating two blocks of data in parallel, the constant pool and the rest. Typically this means generating everything in a buffer while recording the constant pool entries, then writing the constant pool followed by the buffer...

McManus provides a complete source example of performing those steps. While the example seems to be complex, and following it requires some understanding of the Java class file format, McManus's solution illustrates a key aspect of metaprogramming—that a program is just data, and thus a program can be generated and changed as easily as you can generate any other kind of data.

Have you found a similar need to generate Java bytecode on the fly in your projects? What do you think of McManus' solution to the problem of maintaining an interface and an associated class where the interface likely has only a single implementation?

Topic: Eamonn McManus on Dynamic Code Generation Previous Topic   Next Topic Topic: Swing Smashups

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use