④. 参数设置
①. -XX:+UseG1GC:手动指定使用G1收集器执行内存回收任务
②. -XX:G1HeapRegionSize:设置每个Region的大小。值是2的幂,范围是1MB到32MB之间,目标是根据最小的Java堆大小划分出约2048个区域。默认是堆内存的1/2000
③. -XX:MaxGCPauseMillis:设置期望达到的最大Gc停顿时间指标(JVM会尽力实现,但不保证达到)。默认值是200ms
(如果这个值设置很小,如20ms,那么它收集的region会少,这样长时间后,堆内存会满。产生FullGC,FullGC会出现STW,反而影响用户体验)
④. -XX:ParallelGCThread:设置stw时GC线程数的值。最多设置为8(垃圾回收线程)
⑤. -XX:ConcGCThreads:设置并发标记的线程数。将n设置为并行垃圾回收线程数(ParallelGCThreads)的1/4左右
⑥. -XX:Ini tiatingHeapOccupancyPercent:设置触发并发GC周期的Java堆占用率阈值。超过此值,就触发GC。默认值是45
⑤. 调优操作步骤
- ①. G1的设计原则就是简化JVM性能调优,开发人员只需要简单的三步即可完成调优:
- 开启G1垃圾收集器
- 设置堆的最大内存
- 设置最大的停顿时间
- ②. G1中提供了三种垃圾回收模式:YoungGC、Mixed GC和Full GC,在不同的条件下被触发
⑥. Region详解
①. 使用G1收集器时,它将整个Java堆划分成约2048个大小相同的独立Region块,每个Region块大小根据堆空间的实际大小而定,整体被控制在1MB到32MB之间,且为2的N次幂,即1MB, 2MB, 4MB, 8MB, 1 6MB, 32MB。可以通过-XX:G1Hea pRegionSize设定。所有的Region大小相同,且在JVM生命周期内不会被改变
②. 一个region 有可能属于Eden, Survivor 或者0ld/Tenured 内存区域。但是一个region只可能属于一个角色。图中的E表示该region属于Eden内存区域,s表示属于Survivor内存区域,0表示属于0ld内存区域。图中空白的表示未使用的内存空间
③. 垃圾收集器还增加了一种新的内存区域,叫做Humongous内存区域,如图中的H块。主要用于存储大对象,如果超过1. 5个region,就放到H
(对于堆中的大对象,默认直接会被分配到老年代,但是如果它是一个短期存在的大对象,就会对垃圾收集器造成负面影响。为了解决这个问题,G1划分了一个Humongous区,它用来专门存放大对象。如果一个H区装不下一个大对象,那么G1会寻找连续的H区来存储。为了能找到连续的H区,有时候不得不启动Full GC。G1的大多数行为都把H区作为老年代的一部分来看待)
⑦. 记忆集与写屏障
①. 问题:一个Region不可能是孤立的,一个Region中的对象可能被其他对象引用,如新生代中引用了老年代,这个时候垃圾回收时,会去扫描老年代,会出现STW
②. 解决:无论是G1还是分带收集器,JVM都是使用Remembered Set来避免全局扫描。每个Region都有一个对应的Remembered Set;[下面过程需要掌握]
每次Reference类型数据写操作时,都会产生一个Write Barrier暂时
然后检查将要写入的引用指向的对象是否和该Reference类型数据在不同的Region (其他收集器:检查老年代对象是否引用了新生代对象)
如果不同,通过CardTable把相关引用信息记录到引用指向对象的所在Region对应的Remembered Set中;
当进行垃圾收集时,在GC根节点的枚举范围加入Remembered Set;就可以保证不进行全局扫描,也不会有遗漏