![]() | ![]() |
Table of Contents
The development of the jclasslib bytecode viewer is sponsored by ej-technologies GmbH.
jclasslib is a Java class file library that can be used to read, modify and write class files. The jclasslib bytecode viewer displays class files and bytecode and lets you navigate through the class file structure in a browser-like fashion. While the bytecode manipulation part is of interest to developers with specialized development targets such as obfuscators, compilers or code completion engines, the bytecode viewer is a standalone application which is useful for anyone trying to understand the java virtual machine.
To run the jclasslib bytecode viewer you need a Java 1.4 runtime environment or higher, available at http://java.sun.com/j2se/.
The jclasslib bytecode viewer is provided as a Windows installer or as a gzipped tar archive. Besides unpacking it at a suitable location, no further steps are necessary for the installation. Specifically, no external libraries and classpath settings are necessary.
To install the bytecode viewer as a Netbeans module, double click on jclasslib.nbm in Windows, or perform the following steps in the Netbeans IDE: Tools->Update Center and select [Install Manually Downloaded Modules (*.nbm files)]. Add the file jclasslib.nbm in the next step and complete the remaining steps of the installation wizard.
To build jclasslib, you need the ant build tool (>= 1.5) available at http://ant.apache.org/. If you want to build this documentation, you have to install the dcobook DTD and stylesheets. This is done in three steps:
Create a directory docbook in doc/src under the jclasslib root. In this new directory, create the subdirectories dtd and stylesheets.
download the Docbook XML DTD version 4.1.2 from http://www.oasis-open.org/docbook/xml/index.shtml and unpack contents of this zip file directly to the dtd directory created in step 1.
download the Docbook XSL stylesheets from http://sourceforge.net/project/showfiles.php?group_id=21935 and unpack the zip file to the stylesheets directory created in step 1. Rename the first directory which contains all the other files to docbook.
The following ant targets are used for building jclasslib:
ant target | purpose |
---|---|
compile (default) | compile java files to the build directory |
jar | create jar file in the build directory |
doc | build this documentation in the doc directory |
javadoc | build the javadoc documentation in the doc/api directory |
dist | build a distribution of jclasslib in the dist directory. The distribution is created with install4j available at http://www.ej-technologies.com/products/install4j/overview.html. |
clean | cleans all generated files and directories |
Application launchers for Microsoft Windows (jclasslib.exe) and UNIX (jclasslib) are available. The bytecode viewer can also be run by entering
java -jar jclasslib.jar
As an argument, you can pass either the path of a workspace file or the path of a single class file to be opened on startup.
The bytecode viewer allows you to open class files and jar archives (not java files!) with File->Open class file. Class files will be displayed in child windows which are initially maximized. If you select a jar file, a tree will be displayed which lets you to select a class contained within the archive. As you open class files, the classpath will be automatically updated. You can edit the classpath by choosing Classpath->Setup classpath. You can also choose a class from the currently configured classpath by choosing Classpath->Browse classpath and selecting the desired class from the classpath tree. The classpath for a new workspace initially consists of the runtime library of the JRE that is used to run the bytecode viewer.
The currently configured classpath, the currently opened classes, the window positions and the currently selected detail panes for each class constitute a workspace. Workspaces can be saved and loaded with the File->Save workspace and File->Open Workspace actions. A list of the 10 last used workspaces is displayed in the File+Reopen Workspace menu.
As you navigate through constant pool entries and branch offsets in a class, the backward and forward actions will become available. In this way, you can for example examine the details of a constant pool entry and then easily return to the bytecode you were looking at. If you recompile the class while having it opened in the bytecode viewer, you can reload the class file with Browse->Reload (CTRL-R).
The information contained in a class file are accessible via the tree in the left side of the window, closely mirroring the structures as defined in the Java virtual machine specification. The panel to the right side of the tree displays details contained in the selected structure. Green underlined entries are hyperlinks, which lead to a different structure in the tree or to a different offset in a code structure. Red entries - prefixed by verbose explanations in normal font - are values contained in a particular fields of a structure.
The detail view of any attribute structure is always composed of two areas:
The generic info pane showing fields that apply to all attribute structures.
The specific info pane showing fields that apply only to the specified attribute structure.
The main sections of the class file structure tree are:
All fields without sub-structure directly contained in the class file structure.
The runtime constant pool of the class file. All entries are named as suggested in the Java virtual machine specification and are hyperlinked where appropriate. For class references, method references, interface method references and field references a [Show] button is displayed that displays the referenced class or class member. If the referenced class is not the currently displayed class, the bytecode viewer will try to locate the class in the currently configured class path and open it in a new window. If the class is already opened, the existing window will be activated. If the class can not be located, you get a chance to edit the classpath and try again.
All interfaces which are implemented by the class described by the class file numbered from 0 to n - 1.
All fields of the class described by the class file.
All fields of the class described by the class file. Fields entries may themselves be nodes and contain a ConstantValue attribute.
All methods of the class described by the class file. Method entries contain at least a Code attribute. The specific info part of the detail view of a code attribute contains a tabbed pane with 3 tabs showing
the bytecode in a somewhat modified assembly notation like the one produced by javap. The left gutter shows line numbers in small font. The red numbers at the start of each line show the byte offset of the opcode in the current method. Constant pool entries are hyperlinks denoted as #nnn, links to other offset such as in branching instructions are hyperlinks denoted as nnn.
the exception table pertaining to the bytecode.
other fields of the code attribute structure without further sub-structure.
The Code attribute usually contains other attributes itself and is therefore a node in the tree.
To understand the meaning of the classfile structure, its substructures and the bytecode itself, it is useful to have the Java virtual machine specification at hand.
To open a class file in Netbeans, the first step is to either select a java source node or a class file node in the explorer or to activate a Java source file in the source editor. Java sources have to be compiled in order for the bytecode viewer menu entries to be available. The second step is to either right click and navigate to Tools->View class file in the popup menu or to execute Tools->View class file in the main Netbeans menu.
The following UML diagrams for the bytecode manipulation library packages contained in org.gjt.jclasslib and its subpackages give an overview of the general architecture.
To see extensive debugging on stdout while jclasslib reads or writes class files, set the JVM environment variable org.gjt.jclasslib.structures.AbstractStructure.SYSTEM_PROPERTY_DEBUG (= jclasslib.io.debug) to true either by passing -Djclasslib.io.debug=true right after the the java command in the invokation of the apllication of by setting the property via System.setProperty.
To use jclasslib in your own application you need to look at the javadoc documentation and at the source. Here are a few hints on how to begin:
The single most important class is the org.gjt.jclasslib.structures.ClassFile class. All other structures defined in the class file format are hooked up here.
Reading and writing class files is done with the org.gjt.jclasslib.io.ClassFileReader and org.gjt.jclasslib.io.ClassFileWriter classes.
Bytecode is not translated to java classes within a ClassFile structure. To manipulate bytecode as a sequence of opcodes the org.gjt.jclasslib.io.ByteCodeReader and org.gjt.jclasslib.io.ByteCodeWriter classes can be used to convert the bytecode between classes of the org.gjt.jclasslib.bytecode package and byte[] arrays as returned and expected by the ClassFile structure.
Inserting your own instructions into existing bytecode is done by creating a list of instances of org.gjt.jclasslib.io.CodeInsertion and invoking the org.gjt.jclasslib.io.CodeInsertion.apply method. This way, bytecode offsets of branch instructions are shifted to take account for the inserted instructions. Dependant structures such as line number and exception table are updated as well.
Manipulation of the constant pool is most conveniently done via the org.gjt.jclasslib.structures.ConstantPoolUtil class. With its static methods, you can insert higher-level constant pool entries which require other constant pool entries to be genererated with only one method call.