一、JVM
1.JVM介绍
JVM(Java Visual Machine)是Java虚拟机,本质上是一段运行在计算机上的程序,作用就是运行Java字节码文件。
源代码经过编译得到字节码文件,字节码文件通过各类操作系统的JVM解释后生成机器码,再将机器码交给计算机运行。由此Java可以实现Write Once,Run Anywhere,一次编译,到处运行。
2.JVM功能
- 解释运行:运行字节码文件
- 内存管理:自动分配内存,垃圾回收
- 即时编译:对热点代码即时编译,优化性能
3.JVM组成
二、字节码文件
1.字节码文件组成
- 基本信息:魔数(前4个字节是cafebabe),字节码文件对应Java版本号,访问标识符,父类和接口
- 常量池:字符常量池
- 字段:类和接口声明的字段信息
- 方法:类和接口声明的方法信息,含字节码指令
- 属性:源文件的名称
三、运行时数据区
1.运行时数据区组成
运行时数据区就是JVM管理的内存区域
- 线程不共享
程序计数器(唯一不会发生内存泄漏的,保存固定长度地址):存放字节码指令的地址
Java虚拟机栈:线程方法的调用以栈帧形式存储,栈帧(局部变量表、操作数栈、帧数据(动态链接、方法出口))
本地方法栈 - 线程共享
方法区:类的元信息、运行时常量池、字符串常量池(JDK6及之前)
堆:new的对象
内存溢出:内存的使用量超过它的预设的最大量
2.运行时数据区版本迭代
字符串常量池移动到堆的原因:
- 保证方法区大小可控
- 字符串常量池和堆的垃圾回收类似,可使用相同机制回收,提高效率
- 优化intern():JDK6调用intern()会将第一个字符串常量复制到字符串常量池,JDK7之后字符串常量池移动到堆中,字符串常量池保存堆中字符串的引用
方法区从堆中永久代移动到操作系统管理的元空间的原因:
- 减少OutOfMemoryError错误的出现
- 可以专门为方法区设计独有的垃圾回收机制
四、类加载机制
1.类的生命周期
- 加载:类加载器根据全类名通过不同的渠道以二进制流的形式加载字节码文件
加载后,JVM会在方法区中生成一个InstanceKlass对象,用来保存类的全部信息,同时在堆中生成Java.lang.Class对象,目的是可以通过Java代码获取类的信息
- 验证:字节码文件是否符合JVM规范
- 准备:静态变量赋初值
- 解析:将字节码常量池中的符号引用变成指向内存地址的直接引用
- 初始化:执行静态代码块,为静态变量赋值
2.类加载器
JDK8之前
JDK9之后
- 启动类加载器:加载核心类,路径jre/lib
- 扩展类加载器:记载通用非核心类,路径jre/lib/ext
- 应用类加载器:加载应用中的类,路径classpath
- 自定义类加载器:重写findClass(),用于自定义实现类加载方式的加载器
3.双亲委派机制
回答:
-
类加载器和父类加载器
-
双亲委派的过程
-
双亲委派的作用
保证类加载的安全性:防止恶意代码替换JDK中的核心类库,保证核心类库的安全性和完整性
保证类加载的效率:防止一个类被重复加载
4.打破双亲委派机制
自定义类加载器,重写loadClass()
五、垃圾回收机制
1.垃圾回收算法
- 标记清除算法:可达性分析标记,清除
- 复制算法:From空间 + To空间
- 标记整理算法:标记 ,将存活对象移到一端
- 分代GC:如果年轻代中的伊甸园区空间满,先在伊甸园区和From区执行Minor GC,并累计年龄,年龄到15进入老年代。如果老年代空间满,则先用Minor GC,空间仍然不足,Full GC。
优点:
1.通过调节年轻代和老年代的空间比例,适应不同的应用程度,提高性能
2.年轻代和老年代使用不同的垃圾回收算法,一般年轻代使用复制算法,没有内存碎片,老年代使用标记清除或标记整理算法,由程序员自由决定
3.当在年轻代执行Minor GC就可以保证内存空间的使用时,可以不执行Full GC,由此减少STW(Stop The World),即由垃圾回收引起的停顿时间减少
2.垃圾回收器
-
Serial + Serial Old
年轻代:复制算法
老年代:标记整理算法
单线程垃圾回收年轻代和老年代:单CPU下性能良好,多CPU下吞吐量低
-
PS + PO
年轻代:复制算法
老年代:标记整理算法
多线程并行回收年轻代和老年代:PS为了保证吞吐量,JVM会自行调整堆的参数大小
缺点:不保证暂停时间
-
ParNew + CMS
年轻代:复制算法
老年代:标记清除算法
ParNew多线程并发清理年轻代垃圾
CMS关注于暂停时间,允许垃圾清理线程和用户线程同步执行
初始标记:标记GC Root能关联的存活对象
并发标记:标记初始标记的对象的所有对象,用户线程不用暂停
重新标记:并发阶段有些对象可能发生改变,错标漏标
并发清理:清理垃圾,用户线程不用暂停缺点:
1.内存碎片问题,因为标记清理算法
2.当老年代空间不足,退化成Serial Old问题
3.浮动垃圾问题,并发清理时,依然在产生垃圾 -
G1
年轻代:复制算法
老年代:复制算法PS关注吞吐量,可设置最大暂停时间,CMS关注暂停时间,G1垃圾回收器将2个垃圾回收器结合,所以G1垃圾回收器具有如下特点:
1.吞吐量高
2.可设置最大暂停时间
3.可以并行垃圾回收G1会把堆空间划分为大小相等的区域Region,分为Eden、Survivor、Old区
如果一个对象的空间占到Region的一半,则直接放入老年代的大对象区Humongous
年轻代回收(Young GC):记录每个区域的回收时间,根据最大暂停时间来确定回收多少的区域,回收部分的Eden和Suvivor,放入新的区域,作为Suvivor,并把年龄+1,当到达15,移到Old区
混合回收(Mixed GC):当老年代的区域数量达到比例,回收全部的年轻代区,和部分的Old区,选择存活率低的Old区,这样回收效率高
如果每个足够的区域存放存活的对象,会发生Full GC,会导致较长时间的停顿,所以要尽可能保证剩余空间