0
点赞
收藏
分享

微信扫一扫

自己解析class文件

芝婵 2022-02-15 阅读 164



java文件

package com.kq.jvm;

public class SimpleDemo {

private long id;
public String name;

}

javap解析文件

自己解析class文件_常量池


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

自己解析class文件_java_02

第2个常量池 07

07类型是CONSTANT_Class

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

自己解析class文件_常量池_03


第3个常量池 07

同上第2个常量

07 00 13
# name_index=#19

自己解析class文件_java_04

第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)

自己解析class文件_常量池_05

第5个常量池    01

同上

# 01 00 01 4A

4A = J

自己解析class文件_常量池_06

第6个常量池  01

同上

# 01 00 04 6E 61 6D 65

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

自己解析class文件_数据_07


第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

自己解析class文件_java_08


第8个常量池  01

同上

# 6个
01 00 06

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

自己解析class文件_java_09


第9个常量池  01

同上

# 3个
01 00 03


# ()V
28 29 56

自己解析class文件_数据_10

第10个常量池  01

同上

# 4个
01 00 04



# Code
43 6F 64 65

自己解析class文件_常量池_11


第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

自己解析class文件_数据_12


第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

自己解析class文件_java_13


第15个常量池  01

同上

# 10个
01 00 0A


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

自己解析class文件_java_14


第16个常量池  01

同上

# 15个
01 00 0F

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

自己解析class文件_java_15


第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个位置)

自己解析class文件_常量池_16


第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

自己解析class文件_数据_17


第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 中存放着当前类的全限定名


自己解析class文件_数据_18


super_class u2

java/lang/Object

# 03 第3个常量池
00 03

自己解析class文件_常量池_19


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]

自己解析class文件_数据_20

field[0] - access_flags - u2

private

​ACC_PRIVATE​

0x0002

Declared ​​private​​; usable only within the defining class.

# private
00 02

field[0] - name_index - u2

id

# 常量池第4个位置
00 04

自己解析class文件_数据_21

field[0] - descriptor_index - u2

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

自己解析class文件_java_22


field[0] - attributes_count - u2

# 0个attributes_count
00 00


field[0] - attribute_info attributes[attributes_count]

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


field[1]

自己解析class文件_常量池_23


field[1] - access_flags - u2

public

​ACC_PUBLIC​

0x0001

Declared ​​public​​; may be accessed from outside its package.

# public
00 01

field[1] - name_index - u2

name

# 常量池第6个位置
00 06

自己解析class文件_常量池_24

field[1] - descriptor_index - u2

​L​​ ClassName ​​;​

​reference​

an instance of class ClassName

# 常量池第7个位置  是Ljava/lang/String;类型
00 07

自己解析class文件_数据_25


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];
}

自己解析class文件_数据_26

method[0] - access_flags u2

public

​ACC_PUBLIC​

0x0001

Declared ​​public​​; may be accessed from outside its package.

# public
00 01

method[0] - name_index u2

# 第8个位置
00 08

自己解析class文件_数据_27


method[0] - descriptor_index u2

# 常量池第9个位置
00 09

自己解析class文件_java_28


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

自己解析class文件_数据_29


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)

自己解析class文件_数据_30


method - exception_table_length - u2

# 0个exception
00 00


attributes_count

# 2个
00 02

LineNumberTable 

attributes - attribute_name_index - u2

# LineNumberTable
00 0B

自己解析class文件_数据_31

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

自己解析class文件_常量池_32


LocalVariableTable

# 12
00 0C

自己解析class文件_java_33

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
}

自己解析class文件_java_34


自己解析class文件_java_35














举报

相关推荐

0 条评论