阅读量:0
JVM的功能
解释和运行
- 对字节码文件中的指令,实时的解释成机器码,让计算机执行。
内存管理
- 自动为对象、方法等分配内存
- 自动的垃圾回收机制,回收不再使用的对象
即时编译
- 对热点代码进行优化,提高执行效率。
- 将热点代码解释并优化之后放入内存中,下一次使用直接在内存中读取。
常见的虚拟机
- HotSpot(Oracle JDK)
- HotSpot(Open JDK)
- GraalVM
- DragonWell JDK
- Eclipse OpenJ9
JVM的组成
- 类加载器
- 运行时数据区域(JVM管理的内存)
- 执行引擎(即时编译、解释器、垃圾回收器等)
- 本地接口(调用本地已经编译的方法,比如虚拟机中提供的c/c++的方法)
字节码
- 基础信息(魔数、字节码文件对应的java版本号、访问标识(public final等等)、父类和接口)
- 常量池(保存了字符串常量、类或接口名、字段名、主要在字节码指令中使用)
- 字段(当前类或者接口声明的字段信息)
- 方法(当前类或者接口声明的方法信息字节码指令)
- 属性(类的属性,比如源码的文件名,内部类的列表等)
字节码文件的组成部分-Magic魔数(固定为0xCAFEBABE不会改变)
- 文件无法通过文件扩展名来确定文件的类型,文件扩展名可以随意修改,不影响文件内容
- 软件使用文件的头几个字节(文件头)去校验文件的类型,如果软件不支持该类型就会出错
常量池
- 字节码文件中常量池的作用:避免相同的内容重复定义,节省空间。
类的生命周期
- 加载
- 连接 -> 验证 准备 解析
- 初始化
- 使用
- 卸载
加载阶段
- 类加载器根据类的全限定名通过不同的渠道以二进制流的方式或者字节码信息
- 类加载器在加载完类之后,java虚拟机会将字节码中的信息保存到方法区中,生成一个xxKlass对象,保存类的所有信息,里面还包含实现特定功能比如多态的信息
- 在堆中生成一份与方法区中数据类似的java.lang.Class对象,作用是在java代码中去获取类的信息以及存储静态字段的数据,JDK8及以后
连接阶段
验证
- 文件格式验证
- 原信息验证
- 验证程序执行指令的语义
- 符号引用验证
准备
- 静态变量赋初值int为0
- 如果是final修饰的静态变量不会赋初值,而是直接赋值
解析
- 解析阶段主要是将常量池中的符号引用替换为直接引用
- 直接引用不在使用编号,而是使用内存中地址进行访问具体的数据
初始化
- 初始化阶段会执行静态代码块中的代码,并为静态代码赋值,静态变量赋值
- 初始化阶段会执行字节码文件中clinit部分的字节码指令
- 导致类初始化
- 访问一个类的静态变量或者静态方法,注意变量的final修饰的并且等号右边是常量不会触发初始化
- 调用Class.forName(String className)
- new一个该类的对象
- 执行main方法的当前类
- 直接访问父类的静态变量,不会触发子类的初始化
- 子类的初始化clinit调用之前,会先调用父类的clinit初始化方法
- 数组的创建不会导致数组中元素的类进行初始化
- final修饰的变量如果赋值的内容需要执行指令才能得出结果,会执行clinit方法进行初始化