You are on page 1of 9

Java Class Viewer - CodeProject http://www.codeproject.com/Articles/35915/Java-Class-Viewer?displ...

Articles » Languages » Java » Beginners

Java Class Viewer


AmosShi, 25 Apr 2014 MIT

4.95 (29 votes)

Watch the Java class file visually & interactively for the meaning of every byte

Download binary - 598 KB


Download source code - 178 KB (Last Updated on Mar 25, 2014)
Online source code page (Always contains the latest version of source code)

Introduction
Java Class File is one of the key reasons that Java can run on various platforms. The Java class file is designed as a byte stream,
with a specific structure as described in the JVM Spec, chapter 4.

Well, it is not easy for a beginner to understand the VM Spec; Java Class Viewer is a visual yet powerful application which can
show the meaning of each byte of the class file.

1 of 9 25/02/2016 14:30
Java Class Viewer - CodeProject http://www.codeproject.com/Articles/35915/Java-Class-Viewer?displ...

Background
You can ignore this "Background" section if you are not interested in the history of Java Class Viewer.

1. The Reason for Java Class Viewer

Years ago, I was asked to write a plug-in which can hook the Java applications. The principle of the plug-in was simple: Find the
object/class at run time, and try to change its behavior. At that time, I had to read the class file byte by byte via the binary file
reader like Notepad++. It is really not interesting at all; it is boring.

So, I decided to write a Java Class Viewer, which can display the class file visually, and it can display the meaning of each byte of
the class file. This is the reason for creating the Java Class Viewer application.

In the very beginning (September, 2007), Java Class Viewer was a command line tool. And one and a half years later (I am lazy
enough...), the graphical version of this application was created.

2. Java Class Format library

When creating the graphical application, I noticed that this application can be divided into two parts:

1. Java Class File library. It parses the class byte array file, provides various helper classes which can help to get the
information of the parsed class. It may provide more developer friendly information that the Official JDK javac error
message if the class file has any problem. For example: You can easily write a program to list all the fields and methods
in a .class file using this library.
2. Java Class Viewer. It is a swing window application, uses the Java Class Format library, to give a graphical view of the
class file.

Related Libraries
There is some other library available for class file manufacturing and verifying, like the Byte Code Engineering Library (BCEL)
from Apache. The design principle of Java Class File library is quite different from BCEL. BCEL is a powerful library for edit/change
Java class file, and there is also a class file verifier available in BCEL.

Well, it is (almost) impossible to use BCEL to write a Class File Viewer which can show each byte's meaning, since it does not
record the location when parsing the class file; BCEL source code class and method naming convention is not following the JVM
Spec Class File Structure definition strictly, so not easy to understand for beginners.

Well Java Class File library records the offset of the class file when parsing; the library follows the ClassFile structure in JVM
Spec strictly.

If you are running Java Class Viewer, while reading the JVM Spec, it will be much easier for a beginner to understand the Class
file.

The Class File Format


The Class file has the following structure:

ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;

2 of 9 25/02/2016 14:30
Java Class Viewer - CodeProject http://www.codeproject.com/Articles/35915/Java-Class-Viewer?displ...

u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}

You may want to view the section The class File Format in the JVM Spec for a detailed description for the ClassFile
structure. Here is a brief description:

magic - 0xCAFEBABE, the magic number of class file. If the first 4 bytes are not 0xCAFEBABE, it is not recognized as a class file.

minor_version, major_version - The major version and minor version determine the class file version together.

constant_pool_count, cp_info constant_pool[constant_pool_count-1] - Constant pool of the class


file. The constant pool may contain eleven types of constants:

01. class/interface info


02. field reference info
03. method reference info
04. interface method reference info
05. String
06. Integer
07. Float
08. Long
09. Double
10. NameAndType
11. Utf8

access_flags - The access flag of the class

this_class, super_class - The class info of current class and super class. Only the java.lang.Object class's super
class is null; if the super class is not specified for this class, the super class is java.lang.Object.

interfaces_count, interfaces[interfaces_count] - The direct super interfaces.

fields_count, field_info fields[fields_count] - The fields of this class, if there are any.

methods_count, method_info methods[methods_count] - The methods of this class. The Java compiler will
generate a default constructor for a class (inner class excluded) if there is none. So, there will be at least one method in this class.

attributes_count, attribute_info attributes[attributes_count] - The attribute of this class. There


is at least one attribute named "SourceFile" for the file name of the source code.

Parse a Class File using Java Class File Library

1. Parse the Class File

The class org.freeinternals.format.classfile.ClassFile is the parser of class file. It accepts a byte array as
input parameter; the byte array contains the class file. The byte array may come from a .class file, a .jar file, a .war file, etc. Or
alternatively, the byte array may be built by libraries like BCEL.

// ArticleCodeDemo.src.zip - org.freeinternals.demo.jCFL_CodeDemo.extractClassFile()
File file = new File("C:/Temp/File.class");
byte[] classByteArray = Tool.readClassFile(file);
ClassFile classfile = new ClassFile(classByteArray);
// ArticleCodeDemo.src.zip - org.freeinternals.demo.jCFL_CodeDemo.extractJarFile()
File file = new File("C:/Temp/tools.jar");
JarFile jarFile = new JarFile(file, false, JarFile.OPEN_READ);
ZipFile zipFile = jarFile;

3 of 9 25/02/2016 14:30
Java Class Viewer - CodeProject http://www.codeproject.com/Articles/35915/Java-Class-Viewer?displ...

final Enumeration zipEntries = zipFile.entries();


while (zipEntries.hasMoreElements()) {
ZipEntry zipEntry = (ZipEntry) zipEntries.nextElement();
if (!zipEntry.getName().endsWith(".class")) {
continue;
}
byte[] classByteArray = Tool.readClassFile(zipFile, zipEntry);
ClassFile classfile = new ClassFile(classByteArray);
System.out.println();
System.out.println(zipEntry.getName());
jCFL_CodeDemo.printClassFile(classfile);
}

There is a tool class org.freeinternals.javaclassviewer.ui.Tool which can help us to read from a file or a zip
file. We know that .jar and .war files are both in fact in zip format.

The constructor of ClassFile throws an


org.freeinternals.format.classfile.ClassFormatException if the byte array is not a valid class file, or a
java.io.IOException if there is some error in IO. You may surround the statement with try...catch block or add a
throws clause in the method declaration.

2. Get the Information of the Class File

Once we get the ClassFile instance successfully, we can get the information of the class file via the getXxxxx methods.

Here is an example to print out all of the component information of the class file:

// ArticleCodeDemo.src.zip - org.freeinternals.demo.jCFL_CodeDemo.printClassFile()
// Minor & Major version
MinorVersion minorVersion = classfile.getMinorVersion();
System.out.println("Class File Minor Version: " + minorVersion.getValue());
MajorVersion majorVersion = classfile.getMajorVersion();
System.out.println("Class File Major Version: " + majorVersion.getValue());
// Constant Pool
CPCount cpCount = classfile.getCPCount();
System.out.println("Constant Pool size: " + cpCount.getValue());
AbstractCPInfo[] cpArray = classfile.getConstantPool();
for (int i = 1; i < cpCount.getValue(); i++) {
System.out.println(
String.format("Constant Pool [%d]: %s", i, classfile.getCPDescription(i)));
short tag = cpArray[i].getTag();
if ((tag == AbstractCPInfo.CONSTANT_Double) ||
(tag == AbstractCPInfo.CONSTANT_Long)) {
i++;
}
}
// Access flag, this & super class
AccessFlags accessFlags = classfile.getAccessFlags();
System.out.println("Class Modifier: " + accessFlags.getModifiers());
ThisClass thisClass = classfile.getThisClass();
System.out.println("This Class Name Index: " + thisClass.getValue());
System.out.println("This Class Name: " +
classfile.getCPDescription(thisClass.getValue()));
SuperClass superClass = classfile.getSuperClass();
System.out.println("Super Class Name Index: " + superClass.getValue());
if (superClass.getValue() == 0) {
System.out.println("Super Class Name: java.lang.Object");
} else {
System.out.println("Super Class Name: " +
classfile.getCPDescription(superClass.getValue()));
}
// Interfaces
InterfaceCount interfactCount = classfile.getInterfacesCount();
System.out.println("Interface Count: " + interfactCount.getValue());
if (interfactCount.getValue() > 0) {
Interface[] interfaceArray = classfile.getInterfaces();

4 of 9 25/02/2016 14:30
Java Class Viewer - CodeProject http://www.codeproject.com/Articles/35915/Java-Class-Viewer?displ...

for (int i = 0; i < interfaceArray.length; i++) {


System.out.println(
String.format("Interface [%d] Name Index: %d", i,
interfaceArray[i].getValue()));
System.out.println(
String.format("Interface [%d] Name: %s", i,
classfile.getCPDescription(interfaceArray[i].getValue())));
}
}
// Fields
FieldCount fieldCount = classfile.getFieldCount();
System.out.println("Field count: " + fieldCount.getValue());
if (fieldCount.getValue() > 0) {
FieldInfo[] fieldArray = classfile.getFields();
for (int i = 0; i < fieldArray.length; i++) {
System.out.println(String.format("Field [%d]: %s", i,
fieldArray[i].getDeclaration()));
}
}
// Methods
MethodCount methodCount = classfile.getMethodCount();
System.out.println("Method count: " + methodCount.getValue());
if (methodCount.getValue() > 0) {
MethodInfo[] methodArray = classfile.getMethods();
for (int i = 0; i < methodArray.length; i++) {
System.out.println(String.format("Method [%d]: %s", i,
methodArray[i].getDeclaration()));
}
}
// Attributes
AttributeCount attributeCount = classfile.getAttributeCount();
System.out.println("Attribute count: " + attributeCount.getValue());
AttributeInfo[] attributeArray = classfile.getAttributes();
for (int i = 0; i < attributeArray.length; i++) {
System.out.println(String.format("Attribute [%d]: %s", i,
attributeArray[i].getName()));
}

Here are some special notes for the code above.

Constant Pool: The constant pool array is from index 1 to (constant_pool_count-1); and the
CONSTANT_Long_info and CONSTANT_Double_info will take two indexes position while all other types will
take only one position.
Super Class: The super class index will be zero only when the current class is java.lang.Object. Otherwise, it
should be an item in the constant pool.
Interfaces & Fields: One class may have no interfaces or fields, so we need to check the InterfaceCount and
FieldCount variable before getting the array for interface/field.
Methods: For a non-inner class, one class must have at least one method, which is the default instance constructor
created by javac; but for inner class, there can be no method. So we should check the MethodCount variable is not
zero.
Attributes: One class must have at least one attribute, the SourceFile attribute; we don't have to add similar logic
for it.

By using some code just like the above, it is not hard work to write a visual UI control for a class file. And it will be very easy for
us to write any application to analyse the meta data in the class.

Add the Parsed Class File to the Swing Control

1. A Tree Control for the Class File Component Hierarchy

The class org.freeinternals.javaclassviewer.ui.JTreeClassFile is a subclass of JTree, which accepts a


ClassFile object in the constructor. It will add all components of a class file into the tree control.

5 of 9 25/02/2016 14:30
Java Class Viewer - CodeProject http://www.codeproject.com/Articles/35915/Java-Class-Viewer?displ...

2. A Split Container for the Class File Interactive Binary Viewer

The class org.freeinternals.javaclassviewer.ui.JSplitPaneClassFile is a subclass of JSplitPane,


which is divided into two panels: the left panel is the JTreeClassFile, while the right panel is a binary viewer for class file.

While we select each component in the tree, the corresponding bytes will be highlighted; this is the reason for the word
"interactive".

// JavaClassViewer.src.zip - org.freeinternals.javaclassviewer.Main.open_ClassFile()
private JSplitPaneClassFile cfPane;

private void open_ClassFile(final File file) {


this.cfPane = new JSplitPaneClassFile(Tool.readClassFile(file));
this.add(this.cfPane, BorderLayout.CENTER);
this.resizeForContent();
}

For example, after opening the class file File.class (java.io.File), when we select the node for the method getName(),
the corresponding bytes will be highlighted.

If we select the name_index, descriptor_index node for this method, only the index section (for the value 119, 24) will
be highlighted.

If we select the code node in the Code attribute, and open the Opcode tab, the opcodes of this method are extracted.

Java Class Viewer is not a decompiler, it displays the raw code and some comments according to the context. You may refer to
the JVM Spec for the meaning of the opcode. The extracted opcode is partly human readable.

6 of 9 25/02/2016 14:30
Java Class Viewer - CodeProject http://www.codeproject.com/Articles/35915/Java-Class-Viewer?displ...

3. A Tree Control for the ZipFile ( jar, war, etc.)

The class org.freeinternals.javaclassviewer.ui.JTreeZipFile is a subclass of JTree, which accepts a


ZipFile in the constructor. It will build a tree for all entries in the zip file. The .jar/.war file is in fact a zip file.

// JavaClassViewer.src.zip - org.freeinternals.javaclassviewer.Main.open_JarFile()
// Only key logic is left here

private JTreeZipFile zftree;

private void open_JarFile(final File file) {


this.zftree = new JTreeZipFile(new JarFile(file, false, JarFile.OPEN_READ));
this.zftreeContainer = new JPanelForTree(this.zftree);
this.add(this.zftreeContainer, BorderLayout.CENTER);
this.resizeForContent();
}

Here is a screen shot of the ZipFile tree control.

BTW, if we double click an xxxxx.class node, a new window will be opened for the class file.

7 of 9 25/02/2016 14:30
Java Class Viewer - CodeProject http://www.codeproject.com/Articles/35915/Java-Class-Viewer?displ...

Build a Java Class Viewer


Based on the available controls above, it is very easy to write a class file viewer. We just need to add menu/toolbar, and layout
the controls onto a JFrame.

You may need to refer to the source code at the top of this article for details.

The class file viewer is a good starting point to understand Java. We may use it as a tool to study the new feathers provided by
new versions of Java in JVM .class file level.

History
Apr 26, 2009: Created article
Apr 27-29, 2009: Updated article
Aug 17, 2010: Revised links in this article
Dec 08, 2010: Revised links in this article
June 18, 2013: Refactored source code, Updated links, Supported Apple Mac & Windows 7
Mar 25, 2014: Added new feather for class report; updated the download file

License
This article, along with any associated source code and files, is licensed under The MIT License

Share

About the Author

8 of 9 25/02/2016 14:30
Java Class Viewer - CodeProject http://www.codeproject.com/Articles/35915/Java-Class-Viewer?displ...

AmosShi
Software Developer (Senior)
United States

Deliver useful software to the world.

You may also be interested in...


Beginning Java ME: A Simple Fun with the Arduino 101 -
Mandelbrot Viewer Genuino 101

Inside the Hello World Azure connectivity with Edison


Application via Java Class Viewer and controlling it by an
Windows Phone app

Process viewer Game On: Intel® Edison with


the Xadow Wearable Kit

Comments and Discussions


23 messages have been posted for this article Visit http://www.codeproject.com/Articles/35915/Java-Class-Viewer to
post and view comments on this article, or click here to get a print view with messages.

Permalink | Advertise | Privacy | Terms of Use | Mobile Article Copyright 2009 by AmosShi
Selecione o idioma ▼
Web03 | 2.8.160217.1 | Last Updated 25 Apr 2014 Everything else Copyright © CodeProject, 1999-2016

9 of 9 25/02/2016 14:30

You might also like