The javap
command can be used to analyze class files.
For example, we can use the following command to analyze xxx.class
javap -v -p xxx.class
The goal of this project is to generate similar output to that for javap -v -p
Please execute the following command in the root directory of this project
./scripts/constantPool.sh 'java.lang.Object'
Then you should be able to see the comparison for the parse result for the constant pool
The result should look like this
After executing the above command, we can see
- The parse result for
constant pool
generated by this application in output.txt - The parse result for
constant pool
generated byjavap -v -p
in standard.txt
According to 4.1. The ClassFile Structure, class file has the following format
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;
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];
}
This application uses ParseResult.java to hold the parse result for
a class
file.
4.4. The Constant Pool shows all types that constant pool supports. Each of them corresponds to a subclass for CpInfo.java. The mapping is shown below
Constant Type | Value | Corresponding class in this application |
---|---|---|
CONSTANT_Class | 7 | ConstantClass.java |
CONSTANT_Fieldref | ||
9 | ConstantFieldref.java | |
CONSTANT_Methodref | ||
10 | ConstantMethodref.java | |
CONSTANT_InterfaceMethodref | ||
11 | ConstantInterfaceMethodref.java | |
CONSTANT_String | 8 | ConstantString.java |
CONSTANT_Integer | 3 | ConstantInteger.java |
CONSTANT_Float | 4 | ConstantFloat.java |
CONSTANT_Long | 5 | ConstantLong.java |
CONSTANT_Double | 6 | ConstantDouble.java |
CONSTANT_NameAndType | ||
12 | ConstantNameAndType.java | |
CONSTANT_Utf8 | 1 | ConstantUtf8.java |
CONSTANT_MethodHandle | 15 | todo |
CONSTANT_MethodType | 16 | todo |
CONSTANT_InvokeDynamic | 18 | todo |
The entry point for this application is com.study.parser.Main
.
Its logic can be seen as follows
public class Main {
public static void main(String[] args) throws Exception {
String classAsPath = PathUtils.convert(args[0]);
InputStream inputStream = Main.class.getClassLoader().getResourceAsStream(classAsPath);
PrintStreamWrapper printStreamWrapper = new PrintStreamWrapper("scripts/result/output.txt");
BasicInputStream basicInputStream = new BasicInputStream(inputStream);
ParseResult parseResult = new MainParser(basicInputStream).parse();
EnumSet<PresentKind> allKinds = EnumSet.allOf(PresentKind.class);
MainPresenter presenter = new MainPresenter(parseResult, printStreamWrapper, allKinds);
presenter.present();
}
}
There are 2 main steps
MainParser
parses the content of class file and save the result as anParseResult
instance.MainPresenter
presents parse result to a specified file.
Since class
file have several parts, MainParser
parses it accordingly.
The logic is straight-forward.
The parse
method in MainParser
is showen as below.
@Override
public ParseResult parse() {
parseResult = new ParseResult();
parseMagic();
parseVersion();
parseConstantPool();
parseAccessFlags();
parseThisClass();
parseSuperClass();
parseInterfaces();
parseFields();
parseMethods();
parseAttributes();
ensureCompleted();
return parseResult;
}
Many parseXxx methods only contain some logic for parsing some U2/U4, or array of them. Other parseXxx methods (i.e. the following 4 methods) contains some hierarchical logic.
parseConstantPool()
parseFields()
parseMethods()
parseAttributes()
- Chapter 4. The class File Format provides a detailed description for class file format
- How to run
main
method viamvn
: (stackoverflow) Maven Run Project