- -XX:PrintGC。 打印简单GC日志
- 大对象直接进入老年代
- -XX:MaxTenuringThreshold 设置晋升老年代的年龄。默认15,超过年龄的进入老年代
- -XX:PretenureSizeThreshold 设置直接进入老年代的内存大小阀值。(只对DefNew和PreNew有效)
- -XX:+UseTLAB/-XX:-UseTLAB. +:使用TLAB线程内存区。加速对象分配。堆上分配内存会遇到并发分配问题。影响效率;使用TLAB使线程独立使用内存区域,加快内存分配。目前测试是默认开启的。
- -XX:+PrintGCDetails。 打印详细GC日志包括年轻代,老年代等。
- -XX:+PrintHeapAtGC。 GC前后打印堆详细分区信息。
- -Xms。堆空间大小,表示启动时申请的JVM堆大小
- -Xmx。最大堆空间大小,表示JVM能够申请的最大内存。超过98%会内存溢出
- -Xmn,可以设置新生代绝对大小。
- -XX:NewRatio=老年代/新生代。使用这个指令可以指定老年代和新生代的比例。
- 新生代大小一般设置为堆空间Xmx的1/3或者1/4左右
- hotspot虚拟机中新生代GC使用复制算法,所以分区分为eden、from、to三个区域
- -XX:SurvivorRatio=eden/from=eden/to。可以设置eden/from区比例。
- -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Users/wangmeng/OOM。指定当OOM时输出当前heapdump到指定文件。
- client server模式
- GC之复制算法:将内存分区,将可达对象复制到另一个区域,然后清除当前区域。复制算法适用于可达对象不多时,复制数据量很小。清除的对象较多。效率极高。但当每次GC时可达对象很多,机会导致复制变慢,影响效率
- JVM GC使用分代算法。新生代和老年代
- 新生代的改良后的复制算法:JVM新生代将内存分为eden、from、to三个区域,eden用来存放新生成的对象。from、to是两个相等的内存区域也称为survivor幸存者区。每次进行新生代GC时假设使用了from区。那么eden中存活对象、to区存活对象都会被复制到from中。这时eden、to区中的剩余对象都是不可达对象了。可以直接清除。
- 老年代的标记压缩算法,即老年代中可达对象会比清除对象多。所以使用标记清除法,对可达对象进行标记,但是这样会产生内存碎片。所以在jvm中,采用标记压缩法,即标记可达对象后,将他们按顺序移位。然后再对象边界处清除后续所有对象。这样相当于标记清除法+内存整理。
串行回收器
- 新生代串行回收器,复制算法。单线程垃圾回收(避免上下文切换)(独占式-STW) -Client模式默认垃圾收集器。GC标识符:DefNew
- 老年代串行回收器。标记压缩法。单线程垃圾回收,独占式STW。CMS回收器的备用回收器。Full GC Tenured
并行回收器 工作线程数-XX:ParallelGCThreads参数指定
- 新生代ParNew回收器,简单的将DefNew多线程化。在多核CPU上强于串行;在单核CPU上弱于串行。GC标识符:ParNew。工作线程数-XX:ParallelGCThreads参数指定
- 新生代ParallelGC回收器,复制算法,多线程,独占式STW。特点:可关注系统吞吐量,GC标识符:PSYoungGen。-XX:MaxGCPauseMills可设置垃圾收集最大停顿时间,参数是一个>0整数;JVM尽可能将时间控制在参数内。如果设置过小,JVM可能会使用一个小堆(小堆回收快)以满足单次GC在范围内。那么可能会频繁GC,反而降低了吞吐量,增加了GC总时间。这个值个人觉得没什么意义。整数最小就是1了。单次GC基本上在毫秒以下;-XX:GCTimeRatio:设置吞吐量大小。取值0-100整数。即系统不超过m%的时间用于GC。计算公式:1/(n+1) 默认:n=99.即:1/00= 1%。即不超过1%的时间用于GC。个人觉得这个时间也已经比较合理了;-XX:UseAdaptiveSizePolicy,自适应GC策略。这种策略下新生代的大小,eden survivor比例,晋升老年代的对象年龄等参数会自动调整。以达到堆大小、吞吐量、STW的平衡点。配套配置: -Xmx XX:+UseParallelGC -XX:MaxGCPauseMills -XX:GCTimeRatio
- 来年代ParallelOldGC回收器,标记压缩算法,关注吞吐量,并发回收器。GC标识符:PerOldGen
CMS回收器-并发标记清除。关注系统停顿时间
- 使用标记清除算法
- 多线程
- 并行回收
- 缺点,由于可以部分和应用并发,所以无法处理当前正在产生的垃圾。也就是无法清理浮动垃圾。
- 而且由于采用了标记清除算法,会产生内存碎片,必须通过内存整理避免内存碎片问题。
G1-CMS长期替代方案,垃圾优先处理器
缺点:针对大内存分配,可能会横跨多个分区。
- 并行性:多线程并行GC
- 并发性:可以和application交替运行,不会在整个回收期间完全阻塞application运行
- 分区性:将堆进行分代分区,会有多个eden区域和survivor区域和old区。
- 分代GC:依然区分新生代和老年代。之前的回收器要么工作在新生代要么工作在老年代。而G1同时兼顾新生代和老年代。
- 空间整理:CMS使用标记清除法,并不会做内存移动,所以需要在经过一段时间进行一次内存整理;而G1使用标记压缩法,每次都会有效的复制对象。减少空间碎片。
- 可预见性:G1将堆进行了分区,可以只选取部分区域进行内存回收。这样缩小了回收范围。减少了STW时间。
收集过程的4个阶段:新生代GC->并发标记周期->混合收集->如果需要可能进行Full GC
G1新生代GC
eden区被占满触发新生代GC
清空eden区,将eden中存活对象移入survivor区或移入老年代
清理suivivor区,将符合年龄对象晋升老年代
晋升新的老年代
GC标识符 GC pause young eden/survivor
G1并发标记周期-为了降低STW时间,将可以和应用程序并发的部分提取出来
- 初始标记,标记从根节点直接可达的对象。伴随着上面的新生代GC。产生STW。
- 根区域扫描,在初始标记后,进行过一次新生代GC,这时候可通过survivor直接扫描老年代中的可达对象。这时候可以和应用程序并发运行。但这期间是不可以和新的新生代GC并行的,因为新的新生代GC会会修改这个survivor区域。如果在根区域扫描期间发生了新生代GC,那么必须等待当前根区域扫描结束后运行。所以这次新生代GC时间会延长。
- 并发标记,标记整个堆的存活对象,和应用程序并发。
- 重新标记,产生STW。对标记结果进行修正。
- 独占清理,产生STW
- 并发清理
混合回收
在并发标记周期会清理部分垃圾,但主要任务还是标记垃圾。
混合阶段为清理阶段,会先执行正常的年轻代GC,这时eden区域会被清空,并将新生代的存活对象转移到survivor区,然后在老年代中选取被标记多的区域进行清理,被清理的老年代分区的存活对象会被移动到其他老年代分区,同时进行了移动,减少了空间碎片
最后还会触发一次年轻代GC。进而进入并发标记周期,混合GC。循环。
必要时进行Full GC
当老年代被快速填充时,G1会停止并发标记,转入一次Full GC。
参数
-XX:+UseG1GC 开启G1收集器
-XX:MaxGCPauseMills 用于指定目标最大停顿时间,当某次停顿超过这个时间 G1会自动调整新生代、老年代比例;调整堆大小;调整晋升年龄等
-XX:ParallelGCThreads 并行数,工作线程数
-XX:InitiatingHeapOccupancyPercent 堆使用率 默认45 。当堆占用率达到45%时,执行并发标记周期。 该值过大会导致迟迟不能起动并发标记周期,导致引起Full GC的概率会增加,STW时间变长 ;反之,过小的值会导致并发标记周期的启动频繁,大量GC线程抢占CPU。导致性能下降。
-XX:+UseSerialGC:新生代和老年代都使用串行回收器
-XX:+UseParNewGC:新生代使用ParNew回收器,老年代使用串行回收器
-XX:+UseParallelGC: 新生代使用ParallelGC回收器,老年代使用串行回收器
-XX:+UseParallelOldGC 新生代使用ParallelGC回收器,老年代使用ParallelOldGC回收器。均是关注吞吐量的回收器,非常适合对吞吐量敏感的、部署在多核CPU的系统使用。
-XX:+UseConcMarkSweepGC:新生代使用ParNew回收器,老年代使用CMS