Java GC

java垃圾回收器自动回收,没有任何引用链接的就是垃圾

如何确定垃圾

引用计数法:记录引用计数,为0就是垃圾,但是无法解决循环引用找不到垃圾问题
根可达算法:没有同GC roots链接的,都是垃圾
GC基础理论知识及三色标记

垃圾清除算法

Mark-Sweep 标记清除,算法相对简单,两遍扫描(扫描一遍存活的,再扫描一遍未存活的)效率偏低,容易产生碎片,所以不适合eden区。存活对象比较多的情况下效率较高

Copying 拷贝,分为两块内存,将有用的拷贝到另一块内存。空间浪费,移动复制对象,需要调整对对象的引用。适用于对象存活比较少的情况,只扫描一次,效率提高,没有碎片。适用于eden区

Mark-Compact 标记压缩,算法相对复杂,两遍扫描,需要移动对象,效率偏低。不会产生碎片,方便对象分配,不会产生内存减半

堆内存逻辑分区(适用于分代的垃圾回收器,从ZGC开始不再分代了)

GC基础理论知识及三色标记
新生代,老年代1:3
1、新new出来的对象,首先尝试栈上分配,栈上分配不下放到eden区。
2、经过一次垃圾回收后,仍然存活,放到survivor区。再经过一次垃圾回收后,仍然存活,放到另一个survivor区,同时eden区存活的对象也放到这个survivor区里。
3、当来回再survivor区的次数超过15次后,进入老年代。(对象mark word 分代记录4字节,锁两个自己 )

分代及相关参数设置

GC基础理论知识及三色标记
-Xmn 设置年轻代大小
-Xms:最小内存,-Xmx:最大内存

栈上分配和线程本地分配

GC基础理论知识及三色标记

栈上分配(不需要垃圾回收,弹栈就消失了,效率较高)

无逃逸:逃逸分析其实就是分析一个方法中创建出来的‘对象’的作用域是否限制于本方法内。

public void test(){ new hello(); }//没有逃逸
Hello h; public void test(){ h = new hello(); }//逃逸了

支持标量替换:调用时不反回对象类型,而是返回一个基础数据类型

-XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:-UseTLAB 关闭逃逸分析,标量替换,线程本地分配

对象何时进入老年代

GC基础理论知识及三色标记

记忆点,除CMS是6,其他的都是15

动态年龄:当survivor区在互相拷贝时,发现该survivor区+eden,超过自身的一半了,将年龄最大的放到老年代中

对象分配总结

GC基础理论知识及三色标记

1、实例化之后,看能否放到栈中,可以放到栈中,弹出结束
2、不能放到栈中,看对象大小,如果大,放到老年代,Full/major GC结束
3、如果不大,看能否放到线程本地分配中,最终放到eden区
4、GC算法执行,未存活,minor/young GC结束。存活的s1,s2区来回复制,年龄大放到OLD区,

相关文章: