1. 垃圾回收之标记算法
GC
对象被判定为垃圾的标准
- 没有被其他对象引用
判定对象是否为垃圾的算法
引用计数法
- 通过判断对象的引用数量决定对象是否可以被回收
- 每个对象实例都有一个
引用计数器
,被引用则+1, 完成引用则-1 - 任何引用计数为0的实例 可以当做垃圾被回收
优点: 执行效率高, 程序受影响比较小 缺点: 无法检测出循环引用的情况,导致内存泄露
可达性分析算法
通过判断对象的引用链
是否可达到,来决定对象是否可以被回收
可以作为GC Root的对象:
- 虚拟机栈中引用的对象(栈帧中的本地变量表)
- 方法区中的常量引用的对象
- 方法区中类静态属性引用的对象
- 本地方法栈中JNI(Native 方法) 的引用对象
- 活跃线程的引用对象
2. 谈谈你了解的垃圾回收算法
标记-清除法 Mark and Sweep
标记: 从根集合进行扫描,对存活的对象进行标记 清除: 对堆内存从头到尾进行线性遍历,回收不可达对象内存
Mark 阶段 -> Sweep 阶段
存在问题: 碎片化严重,大对象无法找到连续的内存,容易触发下次垃圾回收,outofmemery
复制算法 Coping - 年轻代
适用于对象存活时间比较低的情况
- 分为对象面和空闲面
- 对象在对象面上创建
- 存活对象从对象面复制到空闲面
- 将对象面所有对象内存清除
有点: 解决了碎片化问题, 顺序分配内存,简单高效,适用于对象存活率低的场景–年轻代
标记整理法 - 老年代
整理: 移动所有存活的对象,且按内存地址次序依次排列,然后将末端内存地址以后的内存全部回收。
优点: 避免了内存不连续,不用设置两块内存互换,适用于存活率高的场景
分代收集算法
垃圾回收算法的组合拳
- 按照生命周期的不同划分区域, 以采用不同的垃圾回收算法
- 提高了JVM的垃圾回收效率
Survivor Partitiion 年轻代 复制算法
|Eden Space|From Space| To Space|
Old Generation 老年代 - 标记清除算法 标记整理算法
Tenured Space
Permanen Generation 持久代 -
Permanent Space
GC 的分类
-
Minor GC
新生代: 尽可能的尽快收集掉那些生命周短的对象
-
Full GC
主要回收老年代
Full GC比Minor GC 慢, 但是执行频率低
新生代 1/3 堆空间 Eden 8/10 | from 1/10 | to 1/10
老年代 2/3 堆空间
年轻代垃圾回收过程
Eden 区域满会出发一次Minor GC
Eden 和 From 区域中的对象会全部移动到 to 区域, 对象的age++,同时清空Eden和From区域
- 对象移动到老年代 新生代中的对象达到一定的年龄后会移动到老年代 15岁默认 新生代区域Eden和 Suivivor装不下的大对象会直接移动到老年代
这块区域采用的是复制算法, 通多移动堆顶指针实现垃圾回收
对象如何晋升到老年代
-
经历一定的minor 次数后依然存活的对象
-
Survivor 区域存放不下的对象
-
新生的大对象
-XX: +PretenureSizeThreshold
常用的调优参数
-XX: SurvivorRatio
Eden 和 Survivor 的比值, 默认为8:1-XX: NewRatio
老年代和年轻代内存大小的比例-XX: MaxTenuringThreshold
对象从年轻代晋升到老年代经过GC次数的最大阈值
老年代: 存放生命周期较长的对象
标记清除法 标记整理法
触发Full GC的条件
- 老年代空间不足
- 永久代空间不足(Before Java7)Java8 以后没有永久代,使用元空间代替
- Minor GC时晋升到老年代的平均大小大于老年代的剩余空间
- 调用System.gc()时
- CMG GC时出现promotion failed, concurrent mode failed
- 使用RMI来进行RPC或管理的JDK应用每小时执行一次Full GC