JVM
1. JVM内存区域
私有:虚拟机栈/本地方法栈/程序计数器
虚拟机栈:栈桢,存储局部变量表/动态链接/操作数栈,随着方法的调用而创建,随着方法的结束而销毁
本地方法栈:为Native方法服务
程序计数器:每条线程都有一个独立的PC,唯一不会出现OOM的区域
共享:堆/方法区
堆:存储创建的对象和数组
方法区:存储类信息/静态变量/常量
2. 垃圾回收
2.1 确定垃圾
**引用计数:**对象有关联的引用就+1,对象没有相关联的引用,引用数为0时,表示对象可回收,存在循环引用问题
**根可达算法:**通过GC Roots作为起点,GC Roots和对象之间没有可达路径,表示对象不可达,不可达对象至少经过两次标记,标记后仍不可达,才表示对象可回收
确定GC Roots:
1. 虚拟机栈引用的对象
2. 方法区中静态属性引用的对象
3. 方法区中常量引用的对象
4. 本地方法栈JNI引用的对象
2.2 算法
2.2.1 标记清除(Mark-Sweep)
标记所有需要回收的对象后清除
缺点:内存碎片化严重,大对象找不到利用空间
2.2.2 复制(copying)
将内存划分为相同大小的两块,每次只使用一块,一块内存满后将存活对象复制到另一块,清除已使用对象
缺点:可用内存被压缩
2.2.3 标记整理(Mark-Compact)
标记后将存活对象移动内存的一端,清除边界外的对象
2.3 分代算法
将Java堆内存分为 新生代 老年代 永久代(1.8后元空间)
2.3.1 新生代(1/3):存放新生的对象,由于频繁创建对象,会频繁触发MinorGC
Eden(8/10):新对象的出生地,新对象内存大会直接分配到老年代,Eden区内存不够会触发MinorGC
Survivor From(1/10):上次GC存活的对象,这次被扫描的对象
Survivor To(1/10):保留一次MinorGC的存活对象
MinorGC过程,采用复制算法(复制 --> 清空 --> 互换)
- 将Eden/SurvivorFrom存活对象复制到SurvivorTo,对象年龄+1,默认年龄超过15/SurvivorTo位置不够了就放入老年区
- 清空Eden/SurvivorFrom的对象
- 将SurvivorTo的对象和SurvivorFrom互换,原SurvivorTo成为下次MinorGC的SurvivorFrom区
2.3.2 老年代(2/3)
主要存放应用程序生命周期长的内存对象,比较稳定,不会频繁GC,当无法找到足够大的连续内存给新对象时,会触发MajorGC给对象腾出空间
MajorGC过程,采用标记清除算法
扫描一次所有老年代,标记出存活对象,回收没有标记的对象,为了减少内存损耗,一般需要进行合并或者标记出来下次直接分配,当老年代装不下时,会抛出OOM异常
2.3.3 永久代
GC不会在主程序运行时对永久区进行清理,因此永久代会随着加载的Class增多而导致OOM
2.4 分区算法
将堆划分为多个小区间,每个小区间独立使用,独立回收,可以控制一次回收多个小区间,根据停顿时间合理回收若干个小区间,而不是整个堆,减少一次GC的停顿时长
2.5 垃圾回收器
新生代主要采用复制/标记-清除算法
Serial(单线程,复制算法)
JDK1.3.1之前唯一的GC收集器,只会使用一个CPU或一个线程来完成垃圾收集工作,还会暂停其他所有工作线程,直到垃圾收集结束
ParNew(Serial+多线程)
Serial的多线程垃圾收集器,也会暂停其他所有工作线程,直到垃圾收集结束
默认开启和CPU相同的线程数
Parallel Scavenge(多线程,复制算法)
程序达到一个可控制的吞吐量,自适应调节策略,高效利用CPU,尽快完成程序运算任务
老年代主要采用标记-整理算法
Serial Old(单线程,标记-整理算法)
Serial 垃圾收集器年老代版本
Parallel Old(多线程,标记-整理算法)
Parallel Old 收集器是Parallel Scavenge的年老代版本,使用多线程的标记-整理算法,在 JDK1.6才开始提供
CMS(多线程,标记-整理算法)
获取最短垃圾回收停顿时间,过程:
- 初始标记,标记GC Roots能直接关联的对象,速度快,需要暂停所有工作线程
- 并发标记,进行GC Roots跟踪过程,和用户线程一起工作,不需要暂停工作线程
- 重新标记,修正并发标记时因主程序运行时导致产生变动的那一部分对象的标记记录,需要暂停所有工作线程
- 并发清除,清除GC Roots不可达对象,不需要暂停工作线程
G1(标记-整理算法)
不产生内存碎片,控制停顿时间,实现低停顿垃圾回收。
避免了全区域垃圾收集,将堆内存划分为独立的区域,跟踪这些区域的垃圾收集进度,并在后台维护一个优先级列表,根据允许的时间,优先回收垃圾最多的区域,区域划分和优先级回收机制,确保G1收集器可以在有限时间获取到最高的垃圾回收效率
3. 四种引用类型
强引用
对象赋给引用变量,引用变量就是强引用,对象处于GC Root可达状态,不能被回收
软引用
内存不足时会被回收
弱引用
只要GC就会被回收
虚引用
跟踪对象被垃圾回收的状态
4. 双亲委派
当一个类收到类的加载请求时,不会直接去加载这个类,而是将请求委派给父类去加载,所有上层父类都无法处理这个类时,则会让子类去加载。
自定义 --> 应用类 --> 扩展类 --> 根类