自己解析class文件

 

java文件

package com.kq.jvm;

public class SimpleDemo {

    private long id;
    public String name;

}

javap解析文件

 

class文件

00000000: CA FE BA BE 00 00 00 34 00 14 0A 00 03 00 11 07    J~:>...4........
00000010: 00 12 07 00 13 01 00 02 69 64 01 00 01 4A 01 00    ........id...J..
00000020: 04 6E 61 6D 65 01 00 12 4C 6A 61 76 61 2F 6C 61    .name...Ljava/la
00000030: 6E 67 2F 53 74 72 69 6E 67 3B 01 00 06 3C 69 6E    ng/String;...<in
00000040: 69 74 3E 01 00 03 28 29 56 01 00 04 43 6F 64 65    it>...()V...Code
00000050: 01 00 0F 4C 69 6E 65 4E 75 6D 62 65 72 54 61 62    ...LineNumberTab
00000060: 6C 65 01 00 12 4C 6F 63 61 6C 56 61 72 69 61 62    le...LocalVariab
00000070: 6C 65 54 61 62 6C 65 01 00 04 74 68 69 73 01 00    leTable...this..
00000080: 17 4C 63 6F 6D 2F 6B 71 2F 6A 76 6D 2F 53 69 6D    .Lcom/kq/jvm/Sim
00000090: 70 6C 65 44 65 6D 6F 3B 01 00 0A 53 6F 75 72 63    pleDemo;...Sourc
000000a0: 65 46 69 6C 65 01 00 0F 53 69 6D 70 6C 65 44 65    eFile...SimpleDe
000000b0: 6D 6F 2E 6A 61 76 61 0C 00 08 00 09 01 00 15 63    mo.java........c
000000c0: 6F 6D 2F 6B 71 2F 6A 76 6D 2F 53 69 6D 70 6C 65    om/kq/jvm/Simple
000000d0: 44 65 6D 6F 01 00 10 6A 61 76 61 2F 6C 61 6E 67    Demo...java/lang
000000e0: 2F 4F 62 6A 65 63 74 00 21 00 02 00 03 00 00 00    /Object.!.......
000000f0: 02 00 02 00 04 00 05 00 00 00 01 00 06 00 07 00    ................
00000100: 00 00 01 00 01 00 08 00 09 00 01 00 0A 00 00 00    ................
00000110: 2F 00 01 00 01 00 00 00 05 2A B7 00 01 B1 00 00    /........*7..1..
00000120: 00 02 00 0B 00 00 00 06 00 01 00 00 00 08 00 0C    ................
00000130: 00 00 00 0C 00 01 00 00 00 05 00 0D 00 0E 00 00    ................
00000140: 00 01 00 0F 00 00 00 02 00 10                      ..........

magic - u4

0xCAFEBABE

CA FE BA BE

minor_version - u2

次版本号

00 00

major_version - u2

主版本号

# 00 34

52 是 jdk1.8

constant_pool_count - u2

常量池个数

第一个是null

# 00 14
常量池20个

constant_pool

第1个常量池 0A

0A是10,是CONSTANT_Methodref

CONSTANT_Methodref_info {
    u1 tag;
    u2 class_index;
    u2 name_and_type_index;
}
# 0A 00 03 00 11

指向 03  和  17

第2个常量池 07

07类型是CONSTANT_Class

CONSTANT_Class_info {
    u1 tag;
    u2 name_index;
}
07 00 12
# name_index=#18

 

第3个常量池 07

同上第2个常量

07 00 13
# name_index=#19

第4个常量池   01

01是CONSTANT_Utf8

CONSTANT_Utf8_info {
    u1 tag;
    u2 length;
    u1 bytes[length];
}
# 01 00 02 69 64
tag=01

length=00 02

02后面取2位,就是bytes数据 (6964=id)

第5个常量池    01

同上

# 01 00 01 4A

4A = J

第6个常量池  01

同上

# 01 00 04 6E 61 6D 65

6E = n
61 = a
6D = m
65 = e

 

第7个常量池  01

同上

# 18个
01 00 12  


# Ljava/lang/String;
4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 72 69 6e 67 3b

 

第8个常量池  01

同上

# 6个
01 00 06 

# <init>
3c 69 6e 69 74 3e

 

第9个常量池  01

同上

# 3个
01 00 03


# ()V
28 29 56

第10个常量池  01

同上

# 4个
01 00 04



# Code
43 6F 64 65

 

第11个常量池  01

同上

# 15个
01 00 0f

# LineNumberTable
4C 69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65

 

第12个常量池  01

同上

# 18个
01 00 12

# LocalVariableTable
4C 6F 63 61 6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65

 

第13个常量池  01

同上

# 4个
01 00 04

# this
74 68 69 73

 

第14个常量池  01

同上

# 23个
01 00 17

# Lcom/kq/jvm/SimpleDemo;
4C 63 6F 6D 2F 6B 71 2F 6A 76 6D 2F 53 69 6D 70 6C 65 44 65 6D 6F 3B

 

第15个常量池  01

同上

# 10个
01 00 0A


# SourceFile
53 6F 75 72 63 65 46 69 6C 65

 

第16个常量池  01

同上

# 15个
01 00 0F

# SimpleDemo.java
53 69 6D 70 6C 65 44 65 6D 6F 2E 6A 61 76 61

 

第17个常量池  0C

CONSTANT_NameAndType_info {
    u1 tag;
    u2 name_index;
    u2 descriptor_index;
}

The value of the name_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure 

The value of the descriptor_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure

0C 00 08 00 09

name_index = #8 (常量池第8个位置)
descriptor_index = #9 (常量池第9个位置)

 

第18个常量池  01

CONSTANT_Utf8_info

# 21个
01 00 15


# com/kq/jvm/SimpleDemo
63 6F 6D 2F 6B 71 2F 6A 76 6D 2F 53 69 6D 70 6C 65 44 65 6D 6F

 

第19个常量池  01

CONSTANT_Utf8_info

# 16个位置
01 00 10

# java/lang/Object
6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74

 

access_flags u2

# 33
00 21

 

this_class u2

com/kq/jvm/SimpleDemo

#  #2 第2个常量池
00 02

access_flags下面的两个字节叫做this_class, 它是对当前类的描述。 
它的两个字节的数据是对常量池中的一个CONSTANT_Class_info数据项的一个索引。 
CONSTANT_Class_info中有一个字段叫做name_index , 指向一个CONSTANT_Utf8_info,
在这个CONSTANT_Utf8_info 中存放着当前类的全限定名

 

super_class u2

java/lang/Object

# 03 第3个常量池
00 03

 

interfaces_count  u2

# 0个接口
00 00

interfaces u2

Each value in the interfaces array must be a valid index into the constant_pool table. The constant_pool entry at each value of interfaces[i], where 0 ≤ i < interfaces_count, must be a CONSTANT_Class_info structure representing an interface that is a direct superinterface of this class or interface type, in the left-to-right order given in the source for the type.

u2  interfaces[interfaces_count];

没有实现任何接口,所以interfaces_count=0,这时候也就没有interfaces[]了

fields_count u2

# 2个field
00 02

 

fields[] 

field_info {
    u2             access_flags;
    u2             name_index;
    u2             descriptor_index;
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}

field[0]

field[0] - access_flags - u2

private

ACC_PRIVATE0x0002Declared private; usable only within the defining class.
# private
00 02

field[0] - name_index - u2

id

# 常量池第4个位置
00 04

field[0] - descriptor_index - u2

# 常量池第5个位置  是J  是long类型
00 05

 

field[0] - attributes_count - u2

# 0个attributes_count
00 00

 

field[0] - attribute_info attributes[attributes_count]

由于上面是0,这里不占空间

 

field[1]

 

field[1] - access_flags - u2

public

ACC_PUBLIC0x0001Declared public; may be accessed from outside its package.
# public
00 01

field[1] - name_index - u2

name

# 常量池第6个位置
00 06

field[1] - descriptor_index - u2

L ClassName ;referencean instance of class ClassName
# 常量池第7个位置  是Ljava/lang/String;类型
00 07

 

field[1] - attributes_count - u2

# 0个attributes_count
00 00

 

field[1] - attribute_info attributes[attributes_count]

由于上面是0,这里不占空间

 

methods_count

# 1个方法
00 01

 

method

method_info {
    u2             access_flags;
    u2             name_index;
    u2             descriptor_index;
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}

method[0] - access_flags u2

public

ACC_PUBLIC0x0001Declared public; may be accessed from outside its package.
# public
00 01

method[0] - name_index u2

# 第8个位置
00 08

 

method[0] - descriptor_index u2

# 常量池第9个位置
00 09

 

method[0] - attributes_count  u2

# attributes_count有1个
00 01

 

method[0] - attributes

attribute_info {
    u2 attribute_name_index;
    u4 attribute_length;
    u1 info[attribute_length];
}

 

method[0] - attributes - attribute_name_index - u2

# 常量池第10个位置  Code
00 0A 

 

method[0] - attributes - attribute_length - u4

# length = 32+15 = 47
00 00 00 2F

Code_attribute

Code_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 max_stack;
    u2 max_locals;
    u4 code_length;   # 指令长度是多少 假设是5  往后数5个字节
    u1 code[code_length];   # 2A B7 00 01 B1
    u2 exception_table_length;
    {   u2 start_pc;
        u2 end_pc;
        u2 handler_pc;
        u2 catch_type;
    } exception_table[exception_table_length];
    u2 attributes_count;
    attribute_info attributes[attributes_count];
}

 

method[0] - attributes - info[attribute_length]

# 47
   00 01 00 01 00 00 00 05 2A B7 00 01 B1 00 00
00 02 00 0B 00 00 00 06 00 01 00 00 00 08 00 0C
00 00 00 0C 00 01 00 00 00 05 00 0D 00 0E 00 00

attribute_length项的值表示属性的长度,不包括前六个字节(不包括attribute_name_index、attribute_length),也就是从max_stack开始

max_stack = 00 01 = 1

max_locals = 00 01 = 1

u4 code_length = 00 00 00 05 = 5
code[code_length] = 2A B7 00 01 B1

aload_0 = 42 (0x2a)

invokespecial = 183 (0xb7)  # 后面2位是操作那个对象

00 01  #1 <java/lang/Object.<init>>

return = 177 (0xb1)

 

method - exception_table_length - u2

# 0个exception
00 00

 

attributes_count

# 2个
00 02

LineNumberTable 

attributes - attribute_name_index - u2

# LineNumberTable
00 0B

LineNumberTable_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 line_number_table_length;  # 有下面这样的几组
    {   u2 start_pc;  # 指令码的行数  
        u2 line_number;	  # 源码的行号
    } line_number_table[line_number_table_length];
}
# attribute_length
00 00 00 06

# 00 01   1组
line_number_table_length

# start_pc  0 
00 00

# line_number 8
 00 08

 

LocalVariableTable

# 12
00 0C

LocalVariableTable_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 local_variable_table_length;
    {   u2 start_pc;
        u2 length;
        u2 name_index;
        u2 descriptor_index;
        u2 index;
    } local_variable_table[local_variable_table_length];
}

 

attribute_length

# 12
00 00 00 0C

 

 00 01 00 00 00 05 00 0D 00 0E 00 00

local_variable_table_length = 00 01 = 1

u2 start_pc = 00 00 = 0
u2 length = 00 05 = 5
u2 name_index = 00 0D = #13 = this
u2 descriptor_index = 00 0E = #14 = Lcom/kq/jvm/SimpleDemo;
u2 index = 00 00 

 

 

 

class - attributes_count - u2

# 1个
00 01

 

class - attribute_info 

attribute_info {
    u2 attribute_name_index;  # 00 0F = 15
    u4 attribute_length;  #  00 00 00 02  2字节
    u1 info[attribute_length];   # 00 10 = 16
}

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值