仅为个人理解,如有问题,还希望大家提出来.
GC概念 :
Java堆内存分为新生代和老年代
- Minor GC : 清理年轻代
- Major GC : 清理永久代
- Full GC : 清理整个堆空间—包括年轻代和永久代
新生代中又分为1个Eden区和两个Survior(s0,s1)区域。
垃圾回收算法 :
年轻代 : 标记-复制(复制算法不会产生内存碎片)
老年代 : 标记-整理
对象流程
- 一般情况下,新创建的对象都会被分配到eden区
- 这些对象经过一个minor gc后仍然存活将会被移动到Survior区域中
- 对象在Survior中没熬过一个Minor GC,年龄就会增加一岁
- 当他的年龄到达一定程度(默认15)时,就会被移动到老年代中(但并不代表必须等到年龄到达一定程度才会进入年老代)
- 当eden区满时,还存活的对象将被复制到survior区
- 当一个survior区满时,此区域的存活对象将被复制到另外一个survior区
- 当另外一个也满了的时候,从前一个Survior区复制过来的并且此时还存活的对象,将可能被复制到老年代
优化 :
为降低应用软件的垃圾回收时的停顿,首先考虑的是使用关注系统停顿的 CMS 回收器,其次,为了减少 Full GC 次数,应尽可能将对象预留在年轻代,因为年轻代 Minor GC 的成本远远小于年老代的 Full GC。
- –XX:+UseParNewGC:年轻代使用并行回收器;
- –XX:+UseConcMarkSweepGC:年老代使用 CMS 收集器降低停顿;
- –XX:+SurvivorRatio:设置 Eden 区和 Survivor 区的比例为 8:1。稍大的 Survivor 空间可以提高在年轻代回收生命周期较短的对象的可能性,如果 Survivor 不够大,一些短命的对象可能直接进入年老代,这对系统来说是不利的。
- –XX:TargetSurvivorRatio=90:设置 Survivor 区的可使用率。这里设置为 90%,则允许 90%的 Survivor 空间被使用。默认值是 50%。故该设置提高了 Survivor 区的使用率。当存放的对象超过这个百分比,则对象会向年老代压缩。因此,这个选项更有助于将对象留在年轻代。
- –XX:MaxTenuringThreshold:设置年轻对象晋升到年老代的年龄。默认值是 15 次,即对象经过 15 次 Minor GC 依然存活,则进入年老代。这里设置为 31,目的是让对象尽可能地保存在年轻代区域。
- -XX:PetenureSizeThreshold 设置大对象直接进入年老代的阈值。当对象的大小超过这个值时,将直接在年老代分配。参数-XX:PetenureSizeThreshold 只对串行收集器和年轻代并行收集器有效,并行回收收集器不识别这个参数。
- -XX:MaxTenuringThreshold 来设置,默认值是 15。虽然-XX:MaxTenuringThreshold 的值可能是 15 或者更大,但这不意味着新对象非要达到这个年龄才能进入年老代。事实上,对象实际进入年老代的年龄是虚拟机在运行时根据内存使用情况动态计算的,这个参数指定的是阈值年龄的最大值。即,实际晋升年老代年龄等于动态计算所得的年龄与-XX:MaxTenuringThreshold 中较小的那个。如果希望对象尽可能长时间地停留在年轻代,可以设置一个较大的阈值。
- –Xmx380m –Xms3800m:设置 Java 堆的最大值和初始值相等。一般情况下,为了避免堆内存的频繁震荡,导致系统性能下降,我们的做法是设置最大堆等于最小堆。假设这里把最小堆减少为最大堆的一半,即 1900m,那么 JVM 会尽可能在 1900MB 堆空间中运行,如果这样,发生 GC 的可能性就会比较高;
- -Xss128k:减少线程栈的大小,这样可以使剩余的系统内存支持更多的线程;
- -Xmn2g:设置年轻代区域大小为 2GB;
- –XX:+UseParallelGC:年轻代使用并行垃圾回收收集器。这是一个关注吞吐量的收集器,可以尽可能地减少 GC 时间。
- –XX:ParallelGC-Threads:设置用于垃圾回收的线程数,通常情况下,可以设置和 CPU 数量相等。但在 CPU 数量比较多的情况下,设置相对较小的数值也是合理的;
- –XX:+LargePageSizeInBytes:设置大页的大小。尝试使用大的内存分页.在程序内存不够用时,还可以将不常用的物理内存页转移到其他存储设备上,比如磁盘,这就是大家耳熟能详的虚拟内存。过大的内存分页会导致 JVM 在计算 Heap 内部分区(perm, new, old)内存占用比例时,会出现超出正常值的划分,最坏情况下某个区会多占用一个页的大小。
- –XX:ParallelGCThreads=20:设置 20 个线程进行垃圾回收;
JVM 参数设置 :
// 在实际工作中,我们可以直接将初始的Xms与Xmx相等,这样的好处是可以减少程序运行时垃圾回收次数,从而提高效率。
-Xms:1G; // 初始堆大小为1G
-Xmx:2G; // 最大堆大小为2G
-Xmn:500M;// 轻代大小是500M(包括一个Eden和两个Survivor)
-XX:MaxPermSize:64M; // 设置持久代最大值为64M
-XX:+UseConcMarkSweepGC; // 使用CMS内存收集算法
-XX:SurvivorRatio=3; // Eden区与Survivor区的大小比值为3:1:1 也就是新生代中eden空间和from/to空间的比例
也就是 :
Eden + Survivor + Survivor = 500M;
Eden:Survivor:Survivor=3:1:1
可得出Eden=300M,SurVivor=100M
其它参数 :
-XX:CMSFullGCsBeforeCompaction // 由于并发收集器不对内存空间进行压缩、整理,所以运行一段时间以后会产生“碎片”,使得运行效率降低。此值设置运行多少次GC以后对内存空间进行压缩、整理。
-XX:+UseCMSCompactAtFullCollection // 打开对年老代的压缩。可能会影响性能,但是可以消除碎片
-XX:+PrintGC // 每次触发GC的时候打印相关日志
-XX:+PrintGCDetails // 更详细的GC日志
// 除了可以设置新生代的绝对大小(-Xmn),可以使用(-XX:NewRatio)设置新生代和老年代的比例:-XX:NewRatio=老年代/新生代
-XX:NewRatio=3 如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4
// 不同的堆分布情况,对系统执行会产生一定的影响,在实际工作中,应该根据系统的特点做出合理的配置,基本策略:尽可能将对象预留在新生代,减少老年代的GC次数。
收集器设置 :
- -XX:+UseSerialGC :设置串行收集器
- -XX:+UseParallelGC :设置并行收集器,此配置仅对年轻代有效。即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收集。
- -XX:ParallelGCThreads=20 // 配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。
- -XX:MaxGCPauseMillis=n :设置并行收集最大暂停时间
- -XX:+UseParalledlOldGC :设置并行年老代收集器
- -XX:+UseConcMarkSweepGC :设置并发收集器
- XX:+CMSIncrementalMode :并发收集器设置为增量模式。适用于单CPU情况。
- -XX:GCTimeRatio=n :设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
- 参考 : https://blog.csdn.net/luckystar92/article/details/77320144