

JVM-CLASS文件结构
source link: https://duanguangguang.github.io/2020/04/18/jvm/jvm-class/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

一、Class文件组成内容
1. Class文件格式
演示案例:
public class TestM { private int m; public int inc() { return m + 1; }}
对应的字节码文件:
第一个u4字节代表这是一个class文件:cafe babe(固定的)。
第二个u4字节代表JDK编译的版本号。
-
int i = 3;
字面量就是=右边的东西(3)。
-
- 类和接口的全限定名
- 字段的名称和描述符
- 方法的名称和描述符
常量池总共有21个常量(HEX:00 16)(22-1)
常量池结构表-1
常量池结构表-2
0a:===》10 (对应到常量池结构表查找tag值)代表的Methodref_info
00 06,00 18 ===》#6,#24
09:===》09 代表的Fieldref_info
03,19 ===》#3,#25
07:===》07 代表的Class_info
1a ===》#26
javap -v TestM.class
Constant pool:
#1 = Methodref #6.#24 // java/lang/Object."<init>":()V
#2 = Fieldref #3.#25 // com/example/dodd/jvm/TestM.m:I
#3 = Class #26 // com/example/dodd/jvm/TestM
#4 = Methodref #3.#24 // com/example/dodd/jvm/TestM."<init>":()V
#5 = Methodref #3.#27 // com/example/dodd/jvm/TestM.inc:()I
#6 = Class #28 // java/lang/Object
#7 = Utf8 m
#8 = Utf8 I
#9 = Utf8 <init>
#10 = Utf8 ()V
#11 = Utf8 Code
#12 = Utf8 LineNumberTable
#13 = Utf8 LocalVariableTable
#14 = Utf8 this
#15 = Utf8 Lcom/example/dodd/jvm/TestM;
#16 = Utf8 inc
#17 = Utf8 ()I
#18 = Utf8 main
#19 = Utf8 ([Ljava/lang/String;)V
#20 = Utf8 args
#21 = Utf8 [Ljava/lang/String;
#22 = Utf8 SourceFile
#23 = Utf8 TestM.java
#24 = NameAndType #9:#10 // "<init>":()V
#25 = NameAndType #7:#8 // m:I
#26 = Utf8 com/example/dodd/jvm/TestM
#27 = NameAndType #16:#17 // inc:()I
#28 = Utf8 java/lang/Object
init和clinit
init是实例化初始化方法。使用场景:
- 调用new初始化对象的时候
- 调用反射的时候newInstance()
- 调用clone方法的时候
- ObjectInpustream.getObject()序列化的时候
clinit是类和接口的初始化。使用场景:
class Test{
static int m = 3;
}
class Test{
static int m;
static{
m = 3;
}
}所有的类变量初始化语句和静态初始化语句都被java编译收集到一起,采用clinit初始化方式。采用javap命令查看字节码:
// 类静态变量初始化后出现
static {};
descriptor: ()V
flags: ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: iconst_2
1: putstatic #3 // Field a:I
4: return
LineNumberTable:
line 10: 0解读示例:
public com.example.dodd.jvm.TestM();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 8: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/example/dodd/jvm/TestM;这是TestM的默认构造方法,首先通过invokespecial #1找到虚拟机的第一条指令#1。
第一步,到常量池中找#1常量(#1 = Methodref #6.#24)
#6 指向Class_info的索引项(u2类型数据)
#26 指向NameAndType的索引项(u2类型数据)
第二步,找#6号常量(#6号常量是Class:java/lang/Object)
第三步,找#24号常量(#9:#10)
NameAndType的数据结构(u2:名称常量项的索引,u2:描述符常量项的索引)
第四步,#9对应\
第五步,#10对应()V
至此,搜索的结果就是:
V java/lang/Object.\<init>()
。
ps:类名应该多长?不能超过256。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK