class文件就是java源文件编译的生成的文件。废话不多说,我们通过一个实例来解析.class文件的构成吧。
写一个测试类,代码如下:public final class TestClass {
public int id =123 ;
private String name="中国人";
public void test() {
int a=1;
int b=2;
int c=a+b;
String str=name+"最伟大";
System.out.println(str);
}
}
Javac 后生成的class文件如下:
对应的解析结果如下:
magic number = 0xCAFEBABE -----标准class文件
Version = 50.0
constant pool size = 49
#1 10 Methodref classIndex@13, nameAndType @25
#2 9 Fieldref classIndex@12,nameAndTypeIndex@ 26
#3 8 StringIndex @27
#4 9 Fieldref classIndex@12,nameAndTypeIndex@ 28
#5 7 classIndex @29
#6 10 Methodref classIndex@5, nameAndType @25
#7 10 Methodref classIndex@5, nameAndType @30
#8 8 StringIndex @31
#9 10 Methodref classIndex@5, nameAndType @32
#10 9 Fieldref classIndex@33,nameAndTypeIndex@ 34
#11 10 Methodref classIndex@35, nameAndType @36
#12 7 classIndex @37
#13 7 classIndex @38
#14 1 Utf8 id
#15 1 Utf8 I
#16 1 Utf8 name
#17 1 Utf8 Ljava/lang/String;
#18 1 Utf8 <init>
#19 1 Utf8 ()V
#20 1 Utf8 Code
#21 1 Utf8 LineNumberTable
#22 1 Utf8 test
#23 1 Utf8 SourceFile
#24 1 Utf8 TestClass.java
#25 12 NameAndType name@18, descripter@19
#26 12 NameAndType name@14, descripter@15
#27 1 Utf8 涓浗浜?
#28 12 NameAndType name@16, descripter@17
#29 1 Utf8 java/lang/StringBuilder
#30 12 NameAndType name@39, descripter@40
#31 1 Utf8 鏈?紵澶?
#32 12 NameAndType name@41, descripter@42
#33 7 classIndex @43
#34 12 NameAndType name@44, descripter@45
#35 7 classIndex @46
#36 12 NameAndType name@47, descripter@48
#37 1 Utf8 TestClass
#38 1 Utf8 java/lang/Object
#39 1 Utf8 append
#40 1 Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder;
#41 1 Utf8 toString
#42 1 Utf8 ()Ljava/lang/String;
#43 1 Utf8 java/lang/System
#44 1 Utf8 out
#45 1 Utf8 Ljava/io/PrintStream;
#46 1 Utf8 java/io/PrintStream
#47 1 Utf8 println
#48 1 Utf8 (Ljava/lang/String;)V
access_flags = 49 [public final ]
This class = 12
Super class = 13
下面我详细讲解一下上面的结果和十六进制的图的对应关系
上面的图有红线和蓝线。意思是一样的,交替使用是为了在换行识别的连续性。
<!--EndFragment-->
下面我详细讲解一下上面的结果和十六进制的图的对应关系
上面的图有红线和蓝线。意思是一样的,交替使用是为了在换行识别的连续性。
Class File format | ||
type | descriptor | remark |
u4 | magic | 0xCAFEBABE |
u2 | minor_version |
|
u2 | major_version |
|
u2 | constant_pool_count |
|
cp_info | constant_pool[cosntant_pool_count – 1] | index 0 is invalid |
u2 | access_flags |
|
u2 | this_class |
|
u2 | super_class |
|
u2 | interfaces_count |
|
u2 | interfaces[interfaces_count] |
|
u2 |
| |
field_info | fields[fields_count] |
|
u2 | methods_count |
|
method_info | methods[methods_count] |
|
u2 | attributes_count |
|
attribute_info | attributes[attributes_count] |
|
第一排:[CA FE BA BE 表示魔数: 0xCAFEBABE],[00 00表示次版本号:0],[00 32表示主版本号:50 ] [00 31 表示常量池个数:49],后面就是常量池里面具体的值了.示例性的讲2个吧。[0A tag表示常量类型为10(Methodref),tag枚举见附,00 0D表示class_index,他在常量池的第13个,也就是java/lang/Object]
在第1f0h行常量池结束。常量池后面是
[00 31,表示access_flags:49,意思是该类是public,final],
[00 0C表示this_class,常量池第12个即TestClass],
[00 0D表示super_class,常量池第13个, 表示java/lang/Object],
[00 00表示接口个数为0],
[00 02表示fields_count为2,有两个字段。后面就是对两个字段进行描述]
[00 01 00 0E 00 0F 00 00 分别表示: 00 01字段为public,00 0E表示字段名在常量池第14个,即id,00 0F表示字段描述符I,即int型, 00 00表示属性的个数,他没有所以为0]
[00 02 00 10 00 11 00 00 分别表示:00 02字段修辞符为private,00 10表示字段名在常量池第16个,查为:name,00 11表示字段类型在常量池第17个即:Ljava/lang/String;,00 00表示属性个数为0]
[00 02表示方法个数为2,后面就是详情的方法]
直到240h红线处是该类的构造方法。红线开始是test()方法
直到2a0h红线处方法结束
后面是性属。最后一排01和上排末00表示属性长度为1,后面00 17表示23表示属性的字符串常量在常量池的位置,即SourceFile。表示该属性为源文件。长度为00 02,根据JVM规范,这个值永远为2.具体原因不清楚。最后的00 18表示文件名在常量池的位置为24,即TestClass.java
好了,解析完了。这是通过实战让大家了解class文件的结构。理论参考:http://408036296.blog.163.com/blog/static/1688515020118685836314/?latestBlog
附上tag数据类型:
tag中表示的数据类型:
CONSTANT_Class_info (7)、
CONSTANT_Integer_info (3)、
CONSTANT_Long_info (5)、
CONSTANT_Float_info (4)、
CONSTANT_Double_info (6)、
CONSTANT_String_info (8)、
CONSTANT_Fieldref_info (9)、
CONSTANT_Methodref_info (10)、
CONSTANT_InterfaceMethodref_info (11)、
CONSTANT_NameAndType_info (12)、
CONSTANT_Utf8_info (1)、