Analyze Your Classes
Pages: 1, 2, 3
Class2HTML
This is the utility that traverses a class file and creates five HTML files. These HTML files completely describe the class file by dividing it into constant pool, attributes, byte code, and methods. The fifth file combines all of these into one easy-to-use HTML file.
Run Class2HTML on HelloWorld.class as shown below:
java org.apache.bcel.util.Class2HTML HelloWorld.class
This will create five files in the current directory. Open HelloWorld.html in your browser to see the class contents as illustrated in Figure 1:

Figure 1. HelloWorld.html, as generated by Class2HTML
I have marked the frames into the corresponding class file elements. This is a quick and easy way to map out a class file with the Class2HTML utility.
Static API
Using the static API, let's implement a simple class viewer. This is a simple example that exercises the JavaClass class and is similar to how Class2HTML operates.
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.Code;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.classfile.JavaClass;
public class ClassViewer{
private JavaClass clazz;
public ClassViewer(String clazz){
this.clazz = Repository.lookupClass(clazz);
}
public static void main(String args[]){
if(args.length != 1)
throw new IllegalArgumentException(
"One and only one class at a time!");
ClassViewer viewer = new ClassViewer(args[0]);
viewer.start();
}
private void start(){
if(this.clazz != null){
// first print the structure
// of the class file
System.err.println(clazz);
// next print the methods
Method[] methods = clazz.getMethods();
for(int i=0; i<methods.length; i++){
System.err.println(methods[i]);
// now print the actual
// byte code for each method
Code code = methods[i].getCode();
if(code != null)
System.err.println(code);
}
}else
throw new RuntimeException(
"Class file is null!");
}
}
The first thing that this example does is to look up the class that is to
be mapped by requesting that the Repository load it. This is done
by the Repository.lookupClass(String classname) method. The repository loads this class as a JavaClass
that contains all of the information in the Java Class file format. From then on, it is a simple matter of printing the class file structure using the toString conversion on the JavaClass file and the methods and code.
Dynamic API
We have already seen the code required to create a dynamic class when we visited the BCELifier example. HelloWorldCreator.java creates a dynamic class on the fly. Let us see how we can modify this class dynamically by adding a new method.
import org.apache.bcel.*;
import org.apache.bcel.generic.*;
import org.apache.bcel.classfile.*;
public class ClassModifier implements Constants{
private JavaClass clazz;
private ClassGen classGen;
private ConstantPoolGen cp;
public ClassModifier(String clazz){
this.clazz = Repository.lookupClass(clazz);
this.classGen = new ClassGen(this.clazz);
this.cp = this.classGen.getConstantPool();
}
public static void main(String args[]){
if(args.length != 1)
throw new IllegalArgumentException(
"One and only one class at a time!");
ClassModifier modifier = new ClassModifier(args[0]);
modifier.start();
}
private void start(){
if(this.clazz != null) {
// print the methods BEFORE adding the new one
Method[] methods =
classGen.getJavaClass().getMethods();
System.err.println(
"++++ Before adding new method ++++");
for(int i=0; i<methods.length; i++){
System.err.println(methods[i]);
}
InstructionList il = new InstructionList();
classGen.addMethod(
new MethodGen (ACC_PUBLIC | ACC_STATIC,
Type.VOID,
Type.NO_ARGS,
new String[] { },
"newMethod",
clazz.getClassName(),
IL,
cp).getMethod());
// print the methods AFTER adding the new one
methods = classGen.getJavaClass().getMethods();
System.err.println(
"\n++++ After adding new method ++++");
for(int i=0; i<methods.length; i++){
System.err.println(methods[i]);
}
} else
throw new RuntimeException("Class file is null!");
}
}
This class loads a class file and represents it in the memory using
JavaClass. This part is similar to what I did in the static ClassViewer example. Having
created this representation in memory of the input class, the code above
creates an instance of the ClassGen class, using this representation as
the base:
this.classGen = new ClassGen(this.clazz);
this.cp = this.classGen.getConstantPool();
A new method is then added to this instance of classGen by using the
MethodGen constructor. As you can see, this new method has the access flags of public
and static and is called newMethod. The rest of the code simply
prints a list of methods in the class before and after the method is added.
Run this code using HelloWorld.class as the input class file. You will see the following output:
++++ Before adding new method ++++
public void <init>()
public static void main(String[] arg0)
++++ After adding new method ++++
public void <init>()
public static void main(String[] arg0)
public static void newMethod()
As you can see, the newMethod is added to our class file dynamically without
having to touch the source code.
This has been a superficial treatment of the dynamic part of the API. The idea is to improve performance and add enhancements by being able to dynamically modify class files and not just add trivial methods.
Resources
- The Java language specification is a must-read if you want to know more about the internal workings of the JVM and understand the class file structure.
- The BCEL home page contains a manual that gives a general introduction to the API.
- The mailing lists are a great place to ask experienced developers questions about the API.
- Finally, to really understand how BCEL operates, download the source code and start with a look at the utilities package. The utilities contain a good amount of code that exercise this API.
Vikram Goyal is the author of Pro Java ME MMAPI.
Return to ONJava.com.
-
BCEL is not the only byte code library
2004-03-15 07:41:30 fj_rodriguez [View]
-
cool
2003-11-01 16:57:36 anonymous2 [View]
-
flawed?
2003-10-27 06:23:02 anonymous2 [View]
-
flawed?
2003-11-02 21:59:33 anonymous2 [View]
-
ASM: another similar API
2003-10-27 01:24:01 anonymous2 [View]