G1(并发)收集器
G1收集器(或者垃圾优先收集器)的设计初衷是为了尽量缩短处理超大堆(大于4GB)时产生的停顿。相对于CMS的优势而言是内存碎片的产生率大大降低,设计原则就是简单可行的性能调优
官方文档:https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/
一:jdk8环境下开启G1垃圾收集,
-XX:+UseG1GC -Xmx8g -XX:MaxGCPauseMillis=200
1)-XX:+UseG1GC为开启G1垃圾收集器
2)-Xmx8g 设计堆内存的最大内存为8G
3)-XX:MaxGCPauseMillis=500设置GC的最大暂停时间为500ms,在jdk8.0默认值为200ms。
在内存大小一定的情况下,只需要修改最大暂停时间即可。
二:G1的四种物理空间类型
G1将新生代,老年代的物理空间划分取消了,将堆划分为若干个空间相同的小分区.连续的两个Humongous分区可组合成一个分区。分区的大小由JVM设定,大小在 1-32M,分区数量小于2048.
这些区域可分为四种类型:
(E)eden
新生代,新对像的创建是在新生代.每个线程都有一块独立的区域TLAB用于创建对像,
TLAB的全称是Thread Local Allocation Buffer,即线程本地分配缓存区,一个线程专用的内存分配区域。TLAB区只可被当前线程创建对像,对像也可被其它线程访问。
TLAB的本质其实是三个指针管理的区域:start,top 和 end。
1)start是TLAB内存启始地址。
2)end是TLAB内存尾部地址。与start共同定义了TLAB的所有空间
3)top代表了已使用的空间指针,当top指针到了end的位置,则创建新的TLAB。
每个TLAB大小是固定的,当对像大小大于TLAB时,则直接到eden区进行分配空间创建对像,XX:TLABWasteTargetPercent可设置占用eden分区百分比。TLAB允许浪费空间,设置了最大浪费空间值。
启用TLAB参数:
-XX:UseTLAB
设置TLAB占用eden分区百分比的设置参数:
XX:TLABWasteTargetPercent
(S)survivor
幸存空间。Survivor的存在意义,就是减少被送到老年代的对象,进而减少Full GC的发生,Survivor的预筛选保证,只有经历16次Minor GC还能在新生代中存活的对象,才会被送到老年代。
(O)old
老年代,在对像创建过程中,如果TLAB无空间->eden无空间->老年代创建
(H)Humongous
巨型对像区.一个对象占用的空间超过了分区容量50%以上,默认会被分配在老年代,如果此对像使用时效短,类似下面方法的运行,为了减轻垃圾回收过程的资源消耗,会被放在Humongous区。一个分区放不下,则寻找连续巨型区,寻找失败则启动Full GC.
public void testHumongous(){
HumongousClass humongous=new HumongousClass();
humongous.doSth();
}
图型说明:O为老年代,E为新生代,S为幸存空间,H为巨型对像区
G1使用类似标记整理的回收算法,新生代的垃圾收集依然采用暂停所有应用线程的方式(MaxGCPauseMillis所设置的最大暂停时间便可控制暂停时间)回收过程将新生代存活对象拷贝到老年代或者Survivor空间,拷贝过程中清理无效引用并对部分数据压缩。细节请查看java G1(并发)垃圾收集器(二)的拷贝存活对象