JVM(一)--JVM介绍和Class File
什么是JVM
流程图(代表一次编译 到处运行)
Java虚拟机与物理机对比
Class文件类比输入设备
CPU指令集类比输出设备
JVM类比存储器、控制器、运算器等
JVM products
最常用的目前是HotSpot,可以通过java -version命令查看
Oracle:HotSpot、JRockit
IBM:J9 VM
Ali:TaobaoVM
Zual:Zing
JDK JRE JVM
结合JDK看JVM
(1)能够把Class文件翻译成不同平台的CPU指令集
(2)也是Write Once Run Anywhere的保证
HotSpot JVM Architecture
官网:https://www.oracle.com/technetwork/tutorials/tutorials-1876574.html
Class file
Java Source
Java源码文件、Kotlin源码文件、Groovy源码文件等
public class User {
private Integer age;
private String name = "snail";
private Double salary = 100.0;
private static String address;
public void say() {
System.out.println("snail Say...");
}
public static Integer calc(Integer op1, Integer op2) {
op1 = 3;
Integer result = op1 + op2;
return result;
}
public static void main(String[] args) {
System.out.println(calc(1, 2));
}
}
Early compile
javac User.java 编译成User.class
Class format
官网:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html
Class 文件是一组以 8 位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在 Class 文件之中,中间没有添加任何分隔符,这使得整个 Class 文件中存储的内容几乎全部是程序运行的必要数据,没有空隙存在。
当遇到需要占用 8 位字节以上空间的数据项时,则会按照高位在前(Big-Endian)的方式分割成若干个 8 位字节进行存储。
Class 文件只有两种数据类型:无符号数(基础类型)和表(引用类型)
-
查看字节码文件
使用jdk自带的 javap 指令
javap -v User.class > User.txt
-
查看虚拟机解释执行的二进制字节码
可以使用Notepad++ 安装一个HEX一Editor插件,就可以看到如下
class二进制字节码对照表
ClassFile {
u4 magic; // 魔法数字,表明当前文件是.class文件,固定0xCAFEBABE
u2 minor_version; // 分别为Class文件的副版本和主版本,最小版本
u2 major_version; //最大版本
u2 constant_pool_count; // 常量池计数
cp_info constant_pool[constant_pool_count-1]; //
u2 access_flags; // 类访问标识
u2 this_class; // 当前类
u2 super_class; // 父类
u2 interfaces_count; // 实现的接口数
u2 interfaces[interfaces_count]; // 实现接口信息
u2 fields_count; // 字段数量
field_info fields[fields_count]; // 包含的字段信息
u2 methods_count; // 方法数量
method_info methods[methods_count]; // 包含的方法信息
u2 attributes_count; // 属性数量
attribute_info attributes[attributes_count]; // 各种属性
}
Analyse
(1)cafebabe
The magic item supplies the magic number identifying the class file format
(2)0000 + 0034: minor_version + major_version
16进制的34等于10进制的52,表示JDK的版本为8
(3)0043:constant_pool_count
The value of the constant_pool_count item is equal to the number of entries in the constant_pool table plus one
16进制的43等于10进制的67,表示常量池中常量的数量是66
(4)cp_info:constant_pool[constant_pool_count-1]
The constant_pool is a table of structures representing various string constants, class and interface names, field names,
and other constants that are referred to within the ClassFile structure and its substructures. The format of each constant_pool
table entry is indicated by its first "tag" byte.
The constant_pool table is indexed from 1 to constant_pool_count - 1.
字面量:文本字符串,final修饰的常量等
符号引用:类和接口的全限定名、字段名称和描述符、方法名称和描述符
(5)The constant pool
官网:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4
// u 代表基本信息, info代表复合信息
cp_info {
u1 tag;
u1 info[];
}
Table 4.4-A. Constant pool tags
Constant Type | Value |
---|---|
CONSTANT_Class |
7 |
CONSTANT_Fieldref |
9 |
CONSTANT_Methodref |
10 |
CONSTANT_InterfaceMethodref |
11 |
CONSTANT_String |
8 |
CONSTANT_Integer |
3 |
CONSTANT_Float |
4 |
CONSTANT_Long |
5 |
CONSTANT_Double |
6 |
CONSTANT_NameAndType |
12 |
CONSTANT_Utf8 |
1 |
CONSTANT_MethodHandle |
15 |
CONSTANT_MethodType |
16 |
CONSTANT_InvokeDynamic |
18 |
(6)First constant
由0a可以知道第一个常量的类型对应的10进制为10,所以这表示一个方法引用,查找方法引用对应的 structure
CONSTANT_Methodref_info {
u1 tag;
u2 class_index; //代表的是class_index,表示该方法所属的类在常量池中的索引
u2 name_and_type_index; //代表的是name_and_type_index,表示该方法的名称和类型的索引
}
经过分析可以得出第一个常量表示的形式为
#1 = Methodref #16.#35 // java/lang/Object."<init>":()V
(7)Second constant
由08可以知道第一个常量的类型对应的10进制为8,所以这表示一个String引用,查找方法引用对应的structure
CONSTANT_String_info {
u1 tag;
u2 string_index; //代表的是string_index
}
经过分析可以得出第1、2个常量表示的形式为
#1 = Methodref #16.#35 // java/lang/Object."<init>":()V
#2 = String #36 // snail
反汇编
JDK自带的命令 javap
JVM相对class文件来说可以理解为是操作系统;class文件相对JVM来说可以理解为是汇编语言或者机器语言。