15.垃圾回收
2020-03-05 本文已影响0人
强某某
- 自动垃圾收集
自动垃圾收集是查看堆内存,识别正在使用哪些对象以及哪些对象未被删除以及删除未使用对象的过程。
使用中的对象或引用的对象意味着程序的某些部分仍然维护指向该对象的指针。
程序的任何部分都不再引用未使用的对象或未引用的对象,因此可以回收未引用对象使用的内存。
如何确定内存需要被回收
该过程的第一步称为标记。这是垃圾回收器识别哪些内存正在使用而哪些不在使用的地方
3.png
引用计数在java中几乎不使用,因为存在循环引用的问题(Oa属性关联Ob,Ob属性关联Oa)
可达性分析算法
简单说,将对象及其引用关系看作一个图,选定活动的对象作为GC Roots;
然后跟踪引用链条,如果一个对象和GC Roots之间不可达,也就是不存在引用,那么即可认为是可回收对象
4.png
引用类型
- 强引用:最常见的普通对象引用,只要还有一个强引用指向一个对象,就不会回收
- 软引用:JVM认为内存不足时,才会去试图回收软引用指向的对象。(缓存场景)
- 弱引用:虽然是引用,但随时可能被回收掉
- 虚引用:不能通过它访问对象,供对象被finalize以后,执行指定逻辑的机制(Cleaner)
虚引用应用场景:对象监控,或者销毁执行指定逻辑
可达性级别
- 强可达:一个对象可以有一个或多个线程可以不通过各种引用访问到的情况
- 软可达:就是当我们只能通过软引用才能访问到对象的状态
- 弱可达:只能通过弱引用访问时的状态。当弱引用被清除的时候,就符合销毁条件
- 幻象可达:不存在其他引用,并且finalize过了,只有幻象引用指向这个对象
- 不可达:意味着对象可以被清除了
垃圾收集算法
- 标记-清除算法:首先标识出所有要回收的对象,然后进行清除。
标记、清除过程效率有限,有内存碎片化问题,不适合特别大的堆;收集算法基本基于标记清除的思路进行改进的 - 复制算法:划分两块同等大小的区域,收集时将活着的对象复制打另一块区域;拷贝过程中将对象顺序防止,就可以避免内存碎片化。复制+预留内存,有一定的浪费。
-
标记-整理:类似于标记-清除,但为避免内存碎片化,它会在清理过程中将对象移动,以确保移动后的对象占用连续的内存空间
5.png
分代收集
由上面可知,每种垃圾回收算法都不同,都有劣势优势,所以最终JVM采用了分代收集。
根据对象的存活周期,将内存划分为几个区域,不同区域采用合适的垃圾收集算法。新对象会分配到Eden,如果超过-XX:+pRETENUREsIZEtHRESHOLD:设置大对象直接进入老年代的阈值。
6.png
大对象(复制算法针对大对象性能低)和当新生代内存不足的适合,也会直接进入老年代内存;
由上图可知,Eden采用标记-清除,from和to采用复制算法(每经历一个GC,则该对象的有个标记是经历的次数,当次数超过老年代阈值则进入老年大);老年代采用标记-整理算法
7.png
说明:绿色-使用中,棕色-不再使用,分代收集;新生代:S0:S1:Eden->1:1:8;新生代:老年代->1;2
8.png
垃圾收集器
9.png 10.png上面的各种设置都是建议JVM,而不见得JVM就这样执行,只是尽量
11.png 12.png 13.png