JVM内存的系统级的调优主要的目的是减少Minor GC的频率和Full GC的次数,过多的Minor GC和Full GC是会占用很多的系统资源,影响系统的吞吐量。
针对分代垃圾回收调整部分参数
- 年轻代分三个区,一个Eden区,两个Survivor区(from和to区),可以通过
-XXSurvivorRatio
调整比例作用:默认-XX:SurvivorRatio=8,表示Survivor区与Eden区的大小比值是1:1:8,
在MinorGC过程,如果survivor空间不够大,不能够存储所有的从eden空间和from suvivor空间复制过来活动对象,溢出的对象会被复制到old代,
溢出迁移到old代,会导致old代的空间快速增长。 - 大部分对象在先在Eden区中申请内存作用:可以通过设置
-XX:PreTenureSizeThreShold
大小,令大于这个值的对象直接保存到年老代,避免在Eden区与Survivor区之间频繁地通过复制算法回收内存 - 当Eden区满时,无法为新的对象分配内存时,会进行Minor GC对其回收无用对象占用的内存,如果还有存活对象,则将存活的对象复制到Survivor From区(两个中Survivor对称);然后从Eden区存活下来的对象,就会被复制到From,当这个From区满时,此区的存活对象将被复制到To区,接下来Eden区存活下来的对象就会被复制到To区,经历一定的次数Minor GC后,还存活的对象,将被复制“年老区(Tenured)”。作用:Minor默认15次,可通过
-MaxTenuringThreshold
参数调整年轻代回收次数,防止对象过早进入年老代,降低年老代溢出的可能性 - 年轻代和年老代的默认比例为1:2,即年轻代占堆内存的1/3,年老代占2/3,可调整
-XX:NewRatio
的大小设置年轻和年老的比例。作用:默认-XX:NewRatio=2
,即young:tenured=1:2
,适当调整年轻代大小,可以一定层度上较少Full GC出现的概率
其余性能调优常用参数设置
-Xms and -Xmx (or: -XX:InitialHeapSize and -XX:MaxHeapSize)
:指定JVM的初始和最大堆内存大小,两值可以设置相同,以避免每次垃圾回收完成后JVM重新分配内存。-Xmn
:设置年轻代大小。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。-Xss
:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。-XX:+HeapDumpOnOutOfMemoryError and -XX:HeapDumpPath
:让JVM在发生内存溢出时自动的生成堆内存快照(堆内存快照文件有可能很庞大,推荐将堆内存快照生成路径指定到一个拥有足够磁盘空间的地方。)-XX:OnOutOfMemoryError
:当内存溢发生时,我们甚至可以可以执行一些指令,比如发个E-mail通知管理员或者执行一些清理工作($ java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.hprof -XX:OnOutOfMemoryError =”sh ~/cleanup.sh” MyApp)-XX:PermSize and -XX:MaxPermSize
:设置永久代大小的初始值和最大值(默认:最小值为物理内存的1/64,最大值为物理内存的1/16,永久代在堆内存中是一块独立的区域,这里设置的永久代大小并不会被包括在使用参数-XX:MaxHeapSize 设置的堆内存大小中)-XX:PretenureSizeThreshold
:令大于这个设置值的对象直接在老年代分配。这样做的目的是避免在Eden区及两个Survivor区之间发生大量的内存复制