-XX:+PrintTenuringDistribution
这个参数用于显示每次Minor GC时Survivor区中各个年龄段的对象的大小。
-XX:InitialTenuringThreshol和-XX:MaxTenuringThreshold
用于设置晋升到老年代的对象年龄的最小值和最大值,每个对象在坚持过一次Minor GC之后,年龄就加1
如果 Survivor 相同年龄对象占用空间达到一半,则大于等于该年龄的对象都移入老年代;
-XX:+UseCMSInitiatingOccupancyOnly
标志来命令JVM不基于运行时收集的数据来启动CMS垃圾收集周期。而是,当该标志被开启时,JVM通过CMSInitiatingOccupancyFraction的值进行每一次CMS收集,而不仅仅是第一次。然而,请记住大多数情况下,JVM比我们自己能作出更好的垃圾收集决策。因此,只有当我们充足的理由(比如测试)并且对应用程序产生的对象的生命周期有深刻的认知时,才应该使用该标志。
-XX:CMSInitiatingOccupancyFraction=68
默认CMS是在tenured generation(年老代)占满68%的时候开始进行CMS收集,如果你的年老代增长不是那么快,并且希望降低CMS次数的话,可以适当调高此值;
-XX:+CMSScavengeBeforeRemark 在CMS GC前启动一次ygc,目的在于减少old gen对ygc gen的引用,降低remark时的开销-----一般CMS的GC耗时 80%都在remark阶段
问题四:nio框架占用DirectMemory导致的OutOfMemoryError
处理方式:使用XX:+DisableExplicitGC
增加DirectMemory的大小;
1、DirectMemory不属于java堆内存、分配内存其实是调用操作系统的Os:malloc()函数。
2、容量可通过-XX:MaxDirectMemorySize指定,如果不指定,则默认与Java堆的最大值(-Xmx指定)一样。注意 ibm jvm默认Direct Memory与-Xmx无直接关系。
3、Direct Memory 内存的使用避免Java堆和Native堆中来回复制数据。从某些场景中提高性能。
4、直接ByteBuffer对象会自动清理本机缓冲区,但这个过程只能作为Java堆GC的一部分来执行,因此它们不会自动响应施加在本机堆上的压力。
5、GC仅在Java堆被填满,以至于无法为堆分配请求提供服务时发生,或者在Java应用程序中显示调用System.gc()函数来释放内存(一些NIO框架就是用这个方法释放占用的DirectMemory)。
6、该区域使用不合理,也是会引起OutOfMemoryError。
7、在需要频繁创建Buffer的场合,由于创建和销毁DirectBuffer的代价比较高昂,是不宜使用DirectBuffer的,但是如果能将DirectBuffer进行复用,那么 ,在读写频繁的情况下,它完全可以大幅改善性能。(对DirectBuffer的读写比普通Buffer快,但是对他的创建和销毁比普通Buffer慢)。
1.2 JVM内存分配策略
1.2.1. 对象优先分配在 Eden
首先尝试在 Eden 分配,若 Eden 空间不足,就发起 YoungGC(简称YGC);
- 如果幸存对象(被根对象直接或间接引用)在 SurvivorTo 能放下,则存活对象全部移入 SurvivorTo;
- 如果幸存对象在 SurvivorTo 存放不下,则存活对象全部移入老年代;
如果此时老年代空间不足,则发起一次 FullGC(简称FYC,整个系统停顿,老年代也参与回收);
如果 FullGC 时空间仍然周转不过来,则报 OutOfMemoryError 并导致进程结束;
- 如果YGC/FGC能周转过来,则新对象分配在 Eden 中;
1.2.2. 大对象直接分配在老年代
所谓的大对象是指,需要大量连续内存的 Java 对象,尤其是长字符串或数组,比如 byte[n] 对象;
可以指定多大才算大对象(只对 Serial/ParNew 有效);
1.2.3. 长期存活对象移入老年代
经历 n 次 YGC 仍然存活的对象,下次 YGC 时将被移入老年代;
可以设置该数值:-XX:MaxTenuringThreshold=15(默认)
1.2.4. 永久代满了也会导致 FullGC
老年代、永久代的垃圾收集是捆绑在一起的,因此无论两者谁满了,都会触发两者的FullGC。
1.2.5. 动态对象年龄判定
如果 Survivor 相同年龄对象占用空间达到一半,则大于等于该年龄的对象都移入老年代;
1.2.6. 冒险模式
JDK 6u24 之后,总是开启冒险模式(先尝试 YGC,以免 FGC 频繁);
每次 YGC 之前,如果老年代最大连续空间,大于新生代所有对象空间之和,则 YGC 肯定成功,否则:
- 如果老年代最大连续空间,大于历次晋升老年代的平均值,则先冒险尝试 YGC;
- 如果老年代最大连续空间,小于历次晋升老年代的平均值,则直接 FullGC;