Skip to content

fanofxiaofeng/naive-class-file-parser

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

28 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

How to run

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

Only compare the analysis result for the constant pool

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 diff.png

After executing the above command, we can see

  1. The parse result for constant pool generated by this application in output.txt
  2. The parse result for constant pool generated by javap -v -p in standard.txt

The ClassFile Structure

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.

Constant Pool

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

Main Logic

2 Main Steps

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

  1. MainParser parses the content of class file and save the result as an ParseResult instance.
  2. MainPresenter presents parse result to a specified file.

Step 1: Main Logic in MainParser

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.

  1. parseConstantPool()
  2. parseFields()
  3. parseMethods()
  4. parseAttributes()

Useful materials

  1. Chapter 4. The class File Format provides a detailed description for class file format
  2. How to run main method via mvn: (stackoverflow) Maven Run Project

About

A naive class file parser(still working on it)

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages