Manipulating the Class File with AsmTools

A Java class file is represented with a hardware & OS independent binary format to be loaded & interpreted at runtime. Except the magic number (the first 4 bytes such as CAFEBABE) and the version number (the 8th byte) which are visible or can be manually edited in a hexadecimal way, modifying the majority of the class file’s bytes manually is hard. Sometimes you need more direct control over the layout and data of a classfile – like modifying an attribute or the constantpool for verifier tests. The best tool I’ve used for this is the AsmTools.

In term of the manipulation of class file, the first tool comes to your mind would be ASM (known as the general-purpose Java bytecode manipulation & analysis framework), which has an easy to use Eclipse Plugin that helps with viewing and modifying the bytecode of the class file.  Another alternative is AsmTools, which is an open source project maintained by the OpenJDK community to help to develop tools & tests for java class file specific production. Unlike ASM, AsmTools supports both the manipulation at the bytecode level (the equivalent of ASM or even more powerful than ASM) via Jasm/Jdis and the adjustment of attributes & constantpool via JCod/JDec in the textual representations.

Currently there is no direct link for downloading on the website, which means you have to manually generate an asmtools.jar on your own, following the building instruction as summarized as follows:

[1] download & extract the latest source of ANT from https://ant.apache.org/bindownload.cgi   e.g.

wget  https://downloads.apache.org//ant/binaries/apache-ant-1.10.8-bin.zip
unzip -qq apache-ant-1.10.8-bin.zip

[2] download an OpenJDK from https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/    e.g.

wget  https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.7%2B10_openj9-0.20.0/OpenJDK11U-jdk_x64_linux_openj9_11.0.7_10_openj9-0.20.0.tar.gz
tar -xzf  OpenJDK11U-jdk_x64_linux_openj9_11.0.7_10_openj9-0.20.0.tar.gz

[3] set up the ant-based build environment for asmtools. e.g.

export JAVA_HOME=”…/asmtool/jdk-11.0.7″
export ANT_HOME=”…/asmtools/apache-ant-1.10.8″
export PATH=”$JAVA_HOME/bin:$ANT_HOME/bin:$PATH”

[4] download & extract the source of asmtools. e.g.

wget http://hg.openjdk.java.net/code-tools/asmtools/archive/tip.zip
unzip -qq tip.zip

[5] run “ant” at asmtools/build and asmtools.jar will be generated at asmtools-7.0-build/release/lib

asmtools/build$ ant

preparerelease:
[copy] Copying 1 file to /…/asmtools-7.0-build/release/lib

BUILD SUCCESSFUL

To illustrate how asmtools.jar works to generate a class file with the modified constant pool, let’s get started with a simple HelloWorld program as follows:

public class HelloWorld {
public static void main(String[] args) {
System.out.println(“Hello, World”);
}
}

After compiling the source to a .class file with javac, we first disassembly the class file to a .jcod file with the following command:

java -jar asmtools.jar jdec HelloWorld.class > HelloWorld.jcod (with the following textual format)

class HelloWorld {
0xCAFEBABE;
0; // minor version
55; // version
[] { // Constant Pool
; // first element is empty

Utf8 “SourceFile”; // #13
Utf8 “HelloWorld.java”; // #14
NameAndType #7 #8; // #15
class #23; // #16
NameAndType #24 #25; // #17
Utf8 “Hello, World”; // #18 <——————-  to be updated

} // Constant Pool

0x0021; // access
#5;// this_cpx
#6;// super_cpx

} // end class HelloWorld

In this example,  we update only one word in the printing UTF8 string stored in the constant pool by replacing “World” with “OpenJ9” as follows:

class HelloWorld {

Utf8 “Hello, OpenJ9”; // #18 <—————– “World” is replaced with “OpenJ9”

} // Constant Pool

} // end class HelloWorld

and reassembly the .jcod file back to a .class file with the following command:

$ java -jar asmtools.jar jcoder HelloWorld.jcod     # HelloWorld.class is generated

Till now, we’ve successfully modified the constant pool of class file via AsmTools without messing up the structure inside the class file.

$ java HelloWorld
Hello, OpenJ9                  # The entry in the constant pool is successfully modified

For more details as to how to use the syntax in manipulating your class files appropriately, please refer to https://wiki.openjdk.java.net/display/CodeTools/Chapter+3, https://wiki.openjdk.java.net/display/CodeTools/Appendix+A (JASM Syntax) & https://wiki.openjdk.java.net/display/CodeTools/Appendix+B (JCOD Syntax).

If you’re developing test cases that need explicit control of the classfile structure, then check out the ASMTools project.

Leave a Reply