一、找出垃圾的算法?
1.引用计数算法,
1.原理:
给每个对象设置一个计数器,有地方引用这个对象的时候,计数器+1,引用失效的时候,计数器-1,计数器为0的时候,就销毁对象。
优点|
- 1.实现简单,效率高
缺点
- 1.不能解决循环引用的问题(A引用B,B引用A,但是A,B又不被其他对象所引用)
所以已经弃用了!!
- 2.计数器的增加和减少都是浪费资源.
方法已经弃用,了解即可.
2.根搜索法
1.以GCRoots 作为起点,开始搜索,通过搜索的路径形成引用链条,
当一个对象没有被 GCRoots 的引用链条引用的时候,说明这个对象是不可用的。可以清楚
2.GC对象包括:
- (1)虚拟机栈的引用对象
- (2)方法区类静态属性引用对象
- (3)方法区的常量引用对象
- (4)本地方法栈JNI(Java Native Interface )的引用对象
二、垃圾回收过程(分代收集算法)
1.(基本)垃圾回收的过程点击查看更多
上面的输出太乱我们来分析下
1.如果Eden区满了,出发一次轻度垃圾回收 minor GC ,过程如下.
- (1)比如Eden的10个空间满了,将还需要使用的对象 1
复制
到 幸存区 0(幸存区0和1是动态替换的一般都有一个空白的) - (2)。将消亡的 9 个对象清理掉
2.到下一次Eden区满了,就再 Minor GC ,
- 1.将Eden存活的(假设1个)对象复制到
幸存区1中
, - 2.清理Eden区消亡的对象(假设9个)
- 3.将 幸存0区 的对象(假设3个),存活的
复制
到幸存1区 - 4.将 幸存0区 的对象(假设3个-1个),能晋升的晋升到 老年区**(能晋升的条件??)**
- 5.销毁幸存者0区 还剩下的 1个对象.
注释:
(此时幸存者0区空白,下一次一般幸存者1区空白,所以一般都有一个幸存者空白的)
3.15岁对象进入老年区.
(1)JVM给每个对象定义了一个年龄计数器
(2)如果对象在 Eden区出生,经过一次 轻度垃圾回收 Minor GC 后依旧存活,并且能被 幸存区 Survivor 容纳,对象的年龄就 为 1 ,没经过一次垃圾回收年龄+1,默认15岁,进入老年区
- (可以JVM调优: -XX:MaxTenuringThreshold15)
3.(特殊01)大对象直接进入老年区.
1.什么是 – 大对 象?
(1)大量连续的内存空间的Java对象
(2)比如很长的字符串或者数组.
(3)JVM调参:-XX:PretenureSizeThreshold参数,大于这个参数的值就是大对象.
2.目的:避免在Enden 和 幸存区Survivor 之间发生多次大量内存的复制.
4.(特殊02)动态对象年龄判定
(1)对象并不是只有15岁才进入老年,
(2)当幸存区的某个年龄**(4岁)的所有对象空间大小的总合大于 幸存者空间的一半**,大于或者等于 (4岁)的对象直接进入老年区.
5.(特殊03)分担担保机制:
(1)当发生Minor GC 的时候(需要重Eden转移的对象有20个),发现Survivor幸存者空间不足(只有10个),部分对象无法复制到Survivor幸存者空间,虚拟机可通过分担担保机制将这些对象提前转移到老年区
6 (特殊04)空间分配担保策略,
(1)GC 之前,虚拟机先检查老年区的最大可用连续空间是否大于新生区的所有的对象的总空间,
(2)如果空间够大,GC绝对安全。(通过分担担保机制就能保证安全,)
(3)如果不够大,GC存在风险的可能,
- 1.JVM 会查看 HandlePromotionFailure 设置是否可以冒险
- 2.可以冒险,检查老年区最大可用连续空间是否大于晋升到老年对象的平均大小,
- 3.如果可以冒险,并且 大于 老年对象平均大小---------Minor GC轻度清理.
- 4.如果不能冒险,或者小于老年对象平均大小 -----------Full GC重度清理.
三、垃圾回收算法
1.复制算法
1.定义:
按照内存的容量的大小分为大小相等的2块(HotSpot Eden:幸存Survivor = 8:1),每次只使用其中的一块,当这一块内存用完了,就执行一次轻度GC 然后把活着的 给另一块,使用过的内存一次清理掉.参考新生代的垃圾回收 (比如幸存 0 1 区)
优点 | 效率高没有内存碎片 |
---|---|
缺点 | 1.浪费一般的内存空间 |
局限 | 存活率高的(10个对象9个存活)效率变低,且浪费内存. |
参考 | 新生代的垃圾回收 |
2. 标记清除算法.
1.定义:
清除所有被根搜索法
,标记的无用对象。
3.优点缺点:
优点 | 只用一块内存节约内存. |
---|---|
缺点1 | 内存碎片,内存不连续. |
缺点2 | 标记和清除需要浪费时间,效率不高. |
参考 | 老年区 |
4.图解
3. 标记整理算法
1.定义:
标记对象,先向端移动再清理.
2.步骤:
- 1.标记
- 2.移动
- 3.清除
3.优点缺点:
优点 | 无内存碎片 |
---|---|
缺点1 | 比标记清除算法还慢,效率极低. |
参考 | 老年区 |
4.图解
4. 三大GC算法的比较.
速度 | 复制 —> 清除 —> 整理 |
---|---|
无内存碎片 | 复制 = 整理 —> 清除 |
内存利用率 | 整理 = 清除 —> 复制 |
5. 那个算法最好?(分代收集算法)
答案是,都不好,没有最好的只有最合适的,什么最合适?分代收集算法分带收集算法就是JVM GC 的常用算法。
1.定义:
把堆内存分为新生区和老年区,不同的区域使用不同的算法(1,2,3)
2.步骤(参考二、点)
*1.对象优先在新生代的Eden区出生,然后99%(一般大多数都是局部对象)在新生区的销毁,新生区复制算法
- 2。达到条件的(1. 15岁,或者 2.大对象 或者 3.很多年龄一致的对象)进入老年区 标记清除算法 和 标记整理算法。