此博客为炼数成金JVM教程第十课
目录
- 语言无关性
- 文件结构
- 魔数
- 版本
- 常量池
- 访问符
- 类,超类,接口
- 字段
- 方法
- 属性
语言无关性
JVM直接运行.clss 文件
.class 可以直接从 .java 文件编译过来,但java并不是 JVM的唯一语言,rb,groovy语言等都可以在JVM的平台上执行。
文件结构
u2: 表示无符号的整数,2个byte的整数
u4: 表示无符号的整数,4个byte的整数
- magic: 魔数,表示是否是java文件
- minor_version: 小版本版本号
- major_version: 大版本版本号
- constant_pool_count:常量池的个数
- constant_pool:常量池的内容,数量为常量池的个数减1
- access_flags:访问修饰符(public private protected)
- this_class:当前类是什么
- super_class:超类是什么
- interfaces_count:接口数量
- interfaces:接口
- fields_count:类的字段数量
- fields:字段
- methods_count:方法的数量
- methods:方法信息
- attribute_count:属性的数量
- attributes:属性的信息
magic
U4, 值为 0xCAFEBABE,用来表示这个文件是java的class文件
minor_version & major_version
版本号,都为U2
具体JDK对于的版本号如下
通过版本号就可以知道这个class文件是通过什么版本的java编译出来的,或者目标版本是什么。
常量池
constant_pool_count u2
constant_pool cp_info
- CONSTANT_Utf8 1 UTF-8编码的Unicode字符串
- CONSTANT_Integer 3 int类型的字面值
- CONSTANT_Float 4 float类型的字面值
- CONSTANT_Long 5 long类型的字面值
- CONSTANT_Double 6 double类型的字面值
- CONSTANT_Class 7 对一个类或接口的符号引用
- CONSTANT_String 8 String类型字面值的引用
- CONSTANT_Fieldref 9 对一个字段的符号引用
- CONSTANT_Methodref 10 对一个类中方法的符号引用
- CONSTANT_InterfaceMethodref 11 对一个接口中方法的符号引用
- CONSTANT_NameAndType 12 对一个字段或方法的部分符号引用
CONSTANT_Utf8
- tag 1
- length u2
- bytes[length] // 实际的内容
第一张图:表示无参的返回值为int的方法的描述
第二张图:表示的是返回值是Object的方法的描述
第三张图:表示的是方法的名称
CONSTANT_Integer
tag 3
byte u4
CONSTANT_String
tag 8
string_index u2(指向utf8的索引)
CONSTANT_NameAndType
tag 12
name_index u2(名字, 指向utf8)
descriptor_index u2(描述符类型,指向utf8)
CONSTANT_Class
tag 7
name_index u2(名字,指向utf8)
CONSTANT_Fieldref ,CONSTANT_Methodref ,CONSTANT_InterfaceMethodref
tag 9 ,10, 11
class_index u2 (指向CONSTANT_Class)
name_and_type_index u2 (指向CONSTANT_NameAndType)
access flag u2:类的标示符
this_class
u2
指向常量池的class
super_class
u2
指向常量池的class
可见常量池的重要性: 几乎所有的描述都要索引到常量池当中的数据。
interface_count
u2
接口数量
interfaces
interface_count个interface u2
每个interface是指向CONSTANT_Class的索引
field_count
字段数量
fields
field_count个field_info
field
access_flags u2
name_index u2
descriptor_index u2
attributes_count u2
attribute_info attributes[attributes_count];
access_flags: 字段的访问标识
field
name_index u2
常量池引用,表示字段的名字
descriptor_index
表示字段的类型
B byte
C char
D double
F float
I int
J long
S short
Z boolean
V void
L 对象
Ljava/lang/Object;
[
数组 [[Ljava/lang/String; = String[][]
method
methods_count
方法数量
methods
methods_count个method_info
method_info
access_flags u2
name_index u2
descriptor_index u2
attributes_count u2
attribute_info attributes[attributes_count];
access flag 方法的修饰符
name_index
u2
方法名字,常量池UTF8索引
descriptor_index
u2
方法描述符,用于表达方法的参数和返回值
方法描述符的例子
void inc() ()v
void setId(int) (I)V
int indexOf(char[],int) ([CI)I
attribute
在filed和method中,可以有若干个attribute,类文件也有attribute,用于描述一些额外的信息
attribute_name_index u2
名字,指向常量池的UTF8
attribute_length u4
长度
info[attribute_length] u1
内容
attribute本身也可以包含其他attribute
随着JDK的发展,不断有新的attribute加入
主要的attribute如下所示:
Deprecated
attribute_name_index u2
attribute_length u4
attribute_name_index
指向包含Deprecated的UTF-8常量
attribute_length
为0
ConstantValue
attribute_name_index u2
attribute_length u4
constantvalue_index u2
attribute_name_index
包含ConstantantValue字面量的UTF-8索引
attribute_length
为2
constantvalue_index
常量值,指向常量池,可以是UTF-8,Float, Double 等
Code
LineNumberTable - Code属性的属性
LocalVariableTable - Code属性的属性
Exceptions属性
和Code属性平级
表示方法抛出的异常(不是try catch部分,而是 throws部分)
结构
attribute_name_index u2
attribute_length u4
number_of_exceptions u2
exception_index_table[number_of_exceptions] u2
指向Constant_Class的索引
SourceFile
描述生成Class文件的源码文件名称
结构
attribute_name_index u2
attribute_length u4
固定为2
soucefile_index u2
UTF-8常量索引
class文件结构例子
public class User {
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}