Java虚拟机总体结构
主要分为三个部分:类加载器,运行时数据区(内存结构),执行引擎。下面是这三个结构的具体功能。
1 类加载器
功能:加载class文件到方法区中
Class文件总体结构:
1.魔数 :表示文件是class文件
2.Class文件版本:4个字节
3.常量池 :字母量 符号引用
4.访问标志:类的 public class/interface abstract final 等标志
5.类索引,父类索引,接口索引:类名,父类名,接口名在常量池中的索引
6.字段表集合:类中的变量 field
7.方法表集合:描述类中的方法
8.属性表集合:class文件的辅助信息,附加属性,如源码文件名称
类加载器工作流程:
1.加载阶段:使用双亲委派机制机制加载类
2.链接阶段:
- 验证:保证字节码的正确性
- 准备:静态变量的内存分配和零值初始化
- 解析:将符号引用转换为直接引用
3.初始化阶段:静态(类)变量的直接初始化和静态代码块初始化
2 内存结构(运行时数据区)
1.方法区(元空间-本地内存):存储类信息(类型,域,方法),常量池(字面量,符号引用),JIT代码缓存
2.堆: 存储对象,字符串常量池(固定大小的hash表)
3.虚拟机栈: 线程私有,每个线程都有自己的栈,一个栈中有多个栈帧,每个栈帧对应一个方法调用,栈帧中包括局部变量,操作数栈,动态链接,返回地址等信息
4.本地方法栈: 调用本地方法(c/c++)使用的栈
5.程序计数器: 下一条指令地址
3 执行引擎
功能:解释执行字节码
1.解释器:逐行翻译执行字节码
2.即使编译器(JIT):编译缓存热点代码,提高执行效率
3.垃圾回收器:回收堆和方法区中的对象
垃圾回收:主要针对堆中的对象
垃圾回收层面堆的划分:
新生代:频繁回收新生代,伊甸园空间不够时触发Yong GC
- 伊甸园
- survivor0
- survivor1
老年代:很少回收老年代,老年代空间不够时触发major GC
元空间:几乎不回收元空间,堆空间不够时触发Full GC(回收整个堆和元空间)
对象如何存放:
new的对象先方法伊甸,当伊甸园空间不足时触发Minor GC对伊甸园进行垃圾回收,将幸存者放入幸存者To区,将幸存者中对象幸存次数大于一定值时,将对象放入老年代。
垃圾回收分为两个阶段:垃圾标记阶段,垃圾清除阶段
-
垃圾标记阶段:两种标记算法
- 引用计数:无法解决循环引用问题
- 可达性分析(根搜索算法)
- 先确定GC Root对象(栈引用,方法区中静态变量和常量引用,synchronized持有的对象,虚拟机内部引用的对象)
- 扫描所有GC Root对象,GCRoot对象直接和间接引用的对象都不可回收,其他对象可以回收
-
垃圾清除阶段:三种垃圾收集算法:
- 标记-清除算法:优点,简单;缺点,内存碎片
- 复制算法:优点,高效;缺点,浪费一半内存
- 标记压缩算法:优点,不会产生内存碎片和使用额外内存;缺点,效率较低
其中新生代采用复制算法,老年代采用标记-清除和标记-压缩算法。
不同垃圾回收器对比:
目前主要使用G1垃圾回收器,其回收过程如下,循环进行,其中Full GC不一定执行:
1.Young GC:伊甸园空间不足触发新生代垃圾回收
2.老年代并发标记:当堆空间使用率达到阈值(15%)时,开始老年代并发标记,同时触发Yong GC。
3.混合回收:并发标记完成后进行老年代垃圾回收,同时进行Young GC
4. Full GC:堆空间不足时触发FullGC,回收整个堆空间
G1垃圾回收器的特点:
1.兼具并发和并行:多个gc线程同时工作,并且可以和应用程序线程交替执行,兼顾吞吐量和低延迟
2.分区,分代收集:同时兼顾新生代和老年代,不要求新生代和老年代的空间连续,将内存划分为一个一个的区域,以区域为单位进行垃圾回收,区域内部使用复制算法(两个Region复制),区域之间使用标记-压缩算法,并且优先回收价值最大的Region
3.停顿时间可控:可以设置最大的停顿时间