Jvm参数介绍及调优总结

首先介绍一下新生代、老年代。所谓的新生代和老年代是针对于分代收集算法来定义的,新生代又分为Eden和Survivor两个区。加上老年代就这三个区。数据会首先分配到Eden区 当中(当然也有特殊情况,如果是大对象那么会直接放入到老年代(大对象是指需要大量连续内存空间的java对象),当Eden没有足够空间的时候就会 触发jvm发起一次Minor GC。如果对象经过一次Minor GC还存活,并且又能被Survivor空间接受,那么将被移动到Survivor空 间当中。并将其年龄设为1,对象在Survivor每熬过一次Minor GC,年龄就加1,当年龄达到一定的程度(默认为15)时,就会被晋升到老年代 中了,当然晋升老年代的年龄是可以设置的。jdk的bin目录下的jvisualvm.exe可以辅助分析jvm。

功能开关:

-XX:-AllowUserSignalHandlers:限于Linux和Solaris,默认不启用,允许为java进程安装信号处理器,信号处理参见类:sun.misc.Signal, sun.misc.SignalHandler。

-XX:+DisableExplicitGC:默认启用,禁止在运行期显式地调用System.gc()。

-XX:+FailOverToOldVerifie:Java6新引入选项,默认启用,如果新的Class校验器检查失败,则使用老的校验器(失败原因:因为JDK6最高向下兼容到JDK1.2,而JDK1.2的class info 与JDK6的info存在较大的差异,所以新校验器可能会出现校验失败的情况)。

-XX:+HandlePromotionFailure:java5以前是默认不启用,java6默认启用,关闭新生代收集担保。

-XX:+MaxFDLimit:限于Solaris,默认启用,设置java进程可用文件描述符为操作系统允许的最大值。

-XX:-UseSpinning:java1.4.2和1.5需要手动启用, java6默认已启用,启用多线程自旋锁优化

-XX:PreBlockSpin=10:-XX:+UseSpinning 必须先启用,对于java6来说已经默认启用了,这里默认自旋10次,控制多线程自旋锁优化的自旋次数。

-XX:-RelaxAccessControlCheck:默认不启用,在Class校验器中,放松对访问控制的检查,作用与reflection里的setAccessible类似。

-XX:+ScavengeBeforeFullGC:默认启用,在Full GC前触发一次Minor GC。

-XX:+UseAltSigs:限于Solaris,默认启用,为了防止与其他发送信号的应用程序冲突,允许使用候补信号替代 SIGUSR1和SIGUSR2。

-XX:+UseBoundThreads:限于Solaris, 默认启用,绑定所有的用户线程到内核线程, 减少线程进入饥饿状态(得不到任何cpu time)的次数

-XX:-UseConcMarkSweepGC:默认不启用,启用CMS低停顿垃圾收集器,减少FGC的暂停时间

-XX:+UseGCOverheadLimit:默认启用,限制GC的运行时间。如果GC耗时过长,就抛OOM

-XX:+UseLWPSynchronization:限于solaris,默认启用,使用轻量级进程(内核线程)替换线程同步。

-server: 表示以服务器模式启动,-client表示客户端模式。

-XX:-UseParallelGC:-server时启用,其他情况下,默认不启用,策略为新生代使用并行清除,年老代使用单线程Mark-Sweep-Compact的垃圾收集器。

-XX:-UseParallelOldGC:默认不启用,策略为老年代和新生代都使用并行清除的垃圾收集器

-XX:-UseSerialGC:-client时启用,其他情况下,默认不启用,使用串行垃圾收集器

-XX:+UseTLAB:1.4.2以前和使用-client选项时,默认不启用,其余版本默认启用,启用线程本地缓存区

-XX:+UseSplitVerifier:java5默认不启用, java6默认启用,使用新的Class类型校验器。

-XX:+UseThreadPriorities:默认启用,使用本地线程的优先级

-XX:+UseVMInterruptibleIO:限于solaris,默认启用,在solaris中,允许运行时中断线程

-XX:+UseG1GC  :启用G1 GC,全称Garbage-First Garbage Collector。

-XX:ConcGCThreads=n :并发垃圾收集器使用的线程数量,默认值根据Java虚拟机运行的平台有所变化

性能参数:

-XX:+AggressiveOpts    JDK 5 update 6后引入,但需要手动启用, JDK6默认启用    启用JVM开发团队最新的调优成果。例如编译优化,偏向锁,并行年老代收集等。

-XX:CompileThreshold=10000    默认值:1000    通过JIT编译器,将方法编译成机器码的触发阀值,可以理解为调用方法的次数,例如调1000次,将方法编译为机器码。

-XX:LargePageSizeInBytes=4m    默认4m, amd64位:2m    设置堆内存的内存页大小。

-XX:MaxHeapFreeRatio=70    默认值:70    GC后,如果发现空闲堆内存占到整个预估上限值的70%,则收缩预估上限值.

-XX:MaxNewSize=size    1.3.1 Sparc: 32m, 1.3.1 x86: 2.5m    新生代占整个堆内存的最大值

-XX:MaxPermSize=64m    5.0以后: 64 bit VMs会增大预设值的30%, 1.4 amd64: 96m, 1.3.1 -client: 32m, 其他默认 64m    Perm(俗称方法区,非堆区)占整个堆内存的最大值

-XX:MinHeapFreeRatio=40    40    GC后,如果发现空闲堆内存占到整个预估上限值的40%,则增大上限值

-XX:NewRatio=2    Sparc -client: 8, x86 -server: 8, x86 -client: 12, -client: 4 (1.3),8 (1.3.1+), x86: 12, 其他默认 2    新生代和年老代的堆内存占用比例, 例如2表示新生代占年老代的1/2,占整个堆内存的1/3

-XX:NewSize=2.125m    5.0以后: 64 bit Vms 会增大预设值的30%, x86: 1m, x86, 5.0以后: 640k, 其他默认 2.125m    新生代预估上限的默认值

-XX:ReservedCodeCacheSize=32m    Solaris 64-bit, amd64, -server x86: 48m, 1.5.0_06之前, Solaris 64-bit amd64: 1024m, 其他默认 32m    设置代码缓存的最大值,编译时用

-XX:SurvivorRatio=8    Solaris amd64: 6, Sparc in 1.3.1: 25, Solaris platforms 5.0以前: 32, 其他默认 8    Eden与Survivor的占用比例。例如8表示,一个survivor区占用 1/8 的Eden内存,即1/10的新生代内存,为什么不是1/9?
因为我们的新生代有2个survivor,即S0和S1。所以survivor总共是占用新生代内存的 2/10,Eden与新生代的占比则为 8/10。

-XX:TargetSurvivorRatio=50    50    实际使用的survivor空间大小占比。默认是50%,最高90%

-XX:ThreadStackSize=512    Sparc: 512, Solaris x86: 320 (5.0以前 256), Sparc 64 bit: 1024, Linux amd64: 1024 (5.0 以前 0), 其他默认 512.    线程堆栈大小。

-XX:+UseBiasedLocking    JDK 5 update 6后引入,但需要手动启用, JDK6默认启用    启用偏向锁

-XX:+UseFastAccessorMethods    默认启用    优化原始类型的getter方法性能(get/set:Primitive Type)

-XX:-UseISM    默认启用    启用solaris的ISM

-XX:+UseLargePages    JDK 5 update 5后引入,但需要手动启用, JDK6默认启用    启用大内存分页

-XX:+UseMPSS    1.4.1 之前: 不启用, 其余版本默认启用    启用solaris的MPSS,不能与ISM同时使用

-XX:+UseStringCache    默认开启    启用缓存常用的字符串。

-XX:AllocatePrefetchLines=1    1    Number of cache lines to load after the last object allocation using prefetch instructions generated in JIT compiled code. Default values are 1 if the last allocated object was an instance and 3 if it was an array.

-XX:AllocatePrefetchStyle=1    1    Generated code style for prefetch instructions.

0 – no prefetch instructions are generate*d*,
1 – execute prefetch instructions after each allocation,
2 – use TLAB allocation watermark pointer to gate when prefetch instructions are executed.

-XX:+UseCompressedStrings    Java 6 update 21有一选项    其中,对于不需要16位字符的字符串,可以使用byte[] 而非char[]。对于许多应用,这可以节省内存,但速度较慢(5%-10%)

-XX:+OptimizeStringConcat    在Java 6更新20中引入    优化字符串连接操作在可能的情况下

-XX:+UseCMSInitiatingOccupancyOnly    与下一个参数合用    参数指定CMS垃圾回收器在老年代达到80%的时候开始工作,如果不指定那么默认的值为92%

-XX:CMSInitiatingOccupancyFraction=80

-XX:MaxDirectMemorySize参数:

ByteBuffer有两种:

1.一种是heap ByteBuffer,该类对象分配在JVM的堆内存里面,直接由Java虚拟机负责垃圾回收,

heap ByteBuffer -> -XX:Xmx

2.一种是direct ByteBuffer是通过jni在虚拟机外内存中分配的。通过jmap无法查看该快内存的使用情况。只能通过top来看它的内存使用情况。

direct ByteBuffer -> -XX:MaxDirectMemorySize

JVM堆内存大小可以通过-Xmx来设置,同样的direct ByteBuffer可以通过-XX:MaxDirectMemorySize来设置,此参数的含义是当Direct ByteBuffer分配的堆外内存到达指定大小后,即触发Full GC。注意该值是有上限的,默认是64M,最大为sun.misc.VM.maxDirectMemory(),在程序中中可以获得-XX:MaxDirectMemorySize的设置的值。

调试参数:

-XX:-CITime         打印发费在JIT编译上的时间

-XX:ErrorFile=./hs_err_pid<pid>.log    JDK6中引入    错误文件

-XX:-ExtendedDTraceProbes    JDK6中引入仅在Solaris    启用性能的影响DTrace探测器

-XX:HeapDumpPath=./java_pid<pid>.hprof    1.4.2 update 12, 5.0 update 7    指定HeapDump的文件路径或目录

-XX:-HeapDumpOnOutOfMemoryError    1.4.2 update 12, 5.0 update 7    当抛出OOM时进行HeapDump(HeapDump是一个Java进程在某个时间点上的内存快照)

-XX:+HeapDumpAfterFullGC 这会在运行一次 Full GC 后生成一个堆转储文件。
-XX:+HeapDumpBeforeFullGC 这会在运行一次 Full GC 之前生成一个堆转储文件。 有的情况下(比如,因为执行了多次 Full GC )会生成多个堆转储文件,这时 JVM 会在堆 转储文件的名字上附一个序号。 如果应用会因为堆空间的原因不可预测地抛出
OutOfMemoryError ,而且你需要那一刻的 堆转储来分析错误原因,请尝试打开这些标志。

-XX:OnError=”<cmd args>;<cmd args>”    1.4.2 update 9    当发生错误时执行用户指定的命令

-XX:OnOutOfMemoryError=”<cmd args>; <cmd args>”    1.4.2 update 12, 6    当发生OOM时执行用户指定的命令

-XX:-PrintClassHistogram    1.4.2    当Ctrl+Break发生时打印Class实例信息,与jmap -histo相同

-XX:-PrintConcurrentLocks    6    当Ctrl+Break发生时打印java.util.concurrent的锁信息, 与jstack -l相同

-XX:-PrintCommandLineFlags    5    打印出启动参数行

-XX:-PrintCompilation         当方法被编译时打印信息

-XX:-PrintGC         当GC发生时打印信息

-XX:-PrintGCDetails    1.4.0    打印GC详细信息(这种情况会在GC日志中通过to-space-overflow指示出来。这个代价非常大。)

-XX:-PrintGCTimeStamps    1.4.0    打印GC用时

-XX:-PrintTenuringDistribution         打印Tenuring年龄信息

-XX:-TraceClassLoading         跟踪类加载

-XX:-TraceClassLoadingPreorder    1.4.2    跟踪所有加载的引用类

-XX:-TraceClassResolution    1.4.2    跟踪常量池的变化

-XX:-TraceClassUnloading         跟踪类的卸载

-XX:-TraceLoaderConstraints    6    Trace recording of loader constraints

-XX:+PerfSaveDataToFile         退出时保存jvmstat二进制文件

-XX:ParallelGCThreads=         设置新生代与老年代并行垃圾回收器的线程数

-XX:+UseCompressedOops         Enables the use of compressed pointers (object references represented as 32 bit offsets instead of 64-bit pointers) for optimized 64-bit performance with Java heap sizes less than 32gb.

-XX:+AlwaysPreTouch         Pre-touch the Java heap during JVM initialization. Every page of the heap is thus demand-zeroed during initialization rather than incrementally during application execution.

-XX:AllocatePrefetchDistance=         Sets the prefetch distance for object allocation. Memory about to be written with the value of new objects is prefetched into cache at this distance (in bytes) beyond the address of the last allocated object. Each Java thread has its own allocation point. The default value varies with the platform on which the JVM is running.

-XX:InlineSmallCode=         当编译的代码小于指定的值时,内联编译的代码

-XX:MaxInlineSize=35         内联方法的最大字节数

-XX:FreqInlineSize=         内联频繁执行的方法的最大字节码大小

-XX:LoopUnrollLimit=         Unroll loop bodies with server compiler intermediate representation node count less than this value. The limit used by the server compiler is a function of this value, not the actual value. The default value varies with the platform on which the JVM is running.

-XX:InitialTenuringThreshold=7         设置初始的对象在新生代中最大存活次数

-XX:MaxTenuringThreshold=         设置对象在新生代中最大的存活次数,最大值15,并行回收机制默认为15,CMS默认为4

JVM -XX: 参数介绍 - jack_ou - 博客园

JVM调优总结 -Xms -Xmx -Xmn -Xss等 - jack_ou - 博客园

堆大小设置

典型设置:
1. java -Xmx3550m -Xms3550m -Xmn2g-Xss128k。下面进行解释:
-Xmx3550m:设置JVM最大可用内存为3550M。
-Xms3550m:设置JVM最小内存为3550m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
-Xmn2g:设置年轻代大小为2G。整个JVM内存大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
-Xss128k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
2. java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0。下面进行解释:
-XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5
-XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6
-XX:MaxPermSize=16m:设置持久代大小为16m。
-XX:MaxTenuringThreshold=0:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象在年轻代的存活时间,增加在年轻代即被回收的概论。

回收器选择:

JVM给了三种选择:串行收集器、并行收集器、并发收集器,但是串行收集器只适用于小数据量的情况,所以这里的选择主要针对并行收集器和并发收集器。默认情况下,JDK5.0以前都是使用串行收集器,如果想使用其他收集器需要在启动时加入相应参数。JDK5.0以后,JVM会根据当前系统配置进行判断。
1.吞吐量优先的并行收集器:如上文所述,并行收集器主要以到达一定的吞吐量为目标,适用于科学技术和后台处理等。
典型配置:
java -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20
-XX:+UseParallelGC:选择垃圾收集器为并行收集器。此配置仅对年轻代有效。即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收集。
-XX:ParallelGCThreads=20:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC
-XX:+UseParallelOldGC:配置年老代垃圾收集方式为并行收集。JDK6.0支持对年老代并行收集。
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC  -XX:MaxGCPauseMillis=100
-XX:MaxGCPauseMillis=100:设置每次年轻代垃圾回收的最长时间,如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值。
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC  -XX:MaxGCPauseMillis=100 -XX:+UseAdaptiveSizePolicy
-XX:+UseAdaptiveSizePolicy:设置此选项后,并行收集器会自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低相应时间或者收集频率等,此值建议使用并行收集器时,一直打开。
2.响应时间优先的并发收集器:如上文所述,并发收集器主要是保证系统的响应时间,减少垃圾收集时的停顿时间。适用于应用服务器、电信领域等。
典型配置:
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
-XX:+UseConcMarkSweepGC:设置年老代为并发收集。测试中配置这个以后,-XX:NewRatio=4的配置失效了,原因不明。所以,此时年轻代大小最好用-Xmn设置。
-XX:+UseParNewGC:并发串行收集器,它是工作在新生代的垃圾收集器,它只是将串行收集器多线程化。可与CMS收集同时使用。JDK5.0以上,JVM会根据系统配置自行设置,所以无需再设置此值。
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction:由于并发收集器不对内存空间进行压缩、整理,所以运行一段时间以后会产生“碎片”,使得运行效率降低。此值设置运行多少次GC以后对内存空间进行压缩、整理。
-XX:+UseCMSCompactAtFullCollection:打开对年老代的压缩。可能会影响性能,但是可以消除碎片

辅助信息:
JVM提供了大量命令行参数,打印信息,供调试使用。主要有以下一些:
-XX:+PrintGC
输出形式:[GC 118250K->113543K(130112K), 0.0094143 secs] [Full GC 121376K->10414K(130112K), 0.0650971 secs]

-XX:+PrintGCDetails
输出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs]  [GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs]

-XX:+PrintGCTimeStamps -XX:+PrintGC:PrintGCTimeStamps可与上面两个混合使用, 输出形式:11.851: [GC 98328K->93620K(130112K), 0.0082960 secs]

-XX:+PrintGCApplicationConcurrentTime:打印每次垃圾回收前,程序未中断的执行时间。可与上面混合使用, 输出形式:Application time: 0.5291524 seconds

-XX:+PrintGCApplicationStoppedTime:打印垃圾回收期间程序暂停的时间。可与上面混合使用,输出形式:Total time for which application threads were stopped: 0.0468229 seconds

-XX:PrintHeapAtGC:打印GC前后的详细堆栈信息

输出形式:
34.702: [GC {Heap before gc invocations=7:
 def new generation   total 55296K, used 52568K [0x1ebd0000, 0x227d0000, 0x227d0000)
eden space 49152K,  99% used [0x1ebd0000, 0x21bce430, 0x21bd0000)
from space 6144K,  55% used [0x221d0000, 0x22527e10, 0x227d0000)
to   space 6144K,   0% used [0x21bd0000, 0x21bd0000, 0x221d0000)
tenured generation   total 69632K, used 2696K [0x227d0000, 0x26bd0000, 0x26bd0000)
the space 69632K,   3% used [0x227d0000, 0x22a720f8, 0x22a72200, 0x26bd0000)
compacting perm gen  total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000)
the space 8192K,  35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000)
ro space 8192K,  66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000)
rw space 12288K,  46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000)
34.735: [DefNew: 52568K->3433K(55296K), 0.0072126 secs] 55264K->6615K(124928K)Heap after gc invocations=8:
def new generation   total 55296K, used 3433K [0x1ebd0000, 0x227d0000, 0x227d0000)
eden space 49152K,   0% used [0x1ebd0000, 0x1ebd0000, 0x21bd0000)
from space 6144K,  55% used [0x21bd0000, 0x21f2a5e8, 0x221d0000)
to   space 6144K,   0% used [0x221d0000, 0x221d0000, 0x227d0000)
tenured generation   total 69632K, used 3182K [0x227d0000, 0x26bd0000, 0x26bd0000)
the space 69632K,   4% used [0x227d0000, 0x22aeb958, 0x22aeba00, 0x26bd0000)
compacting perm gen  total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000)
the space 8192K,  35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000)
ro space 8192K,  66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000)
rw space 12288K,  46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000)
}, 0.0757599 secs]

-Xloggc:filename:与上面几个配合使用,把相关日志信息记录到文件以便分析。

常见配置汇总

  1. 堆设置
    1. -Xms:初始堆大小  默认物理内存的1/64
    2. -Xmx:最大堆大小 默认物理内存的1/4
    3. -XX:NewSize=n:设置年轻代大小
    4. -XX:NewRatio=n:设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4
    5. -XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5
    6. -XX:MaxPermSize=n:设置持久代大小
  2. 收集器设置
    1. -XX:+UseSerialGC:设置串行收集器
    2. -XX:+UseParallelGC:设置并行收集器
    3. -XX:+UseParalledlOldGC:设置并行年老代收集器
    4. -XX:+UseConcMarkSweepGC:设置并发收集器
  3. 垃圾回收统计信息
    1. -XX:+PrintGC
    2. -XX:+PrintGCDetails
    3. -XX:+PrintGCTimeStamps
    4. -Xloggc:filename
  4. 并行收集器设置
    1. -XX:ParallelGCThreads=n:设置并行收集线程数。
    2. -XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间
    3. -XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
  5. 并发收集器设置
    1. -XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。
    2. -XX:ParallelGCThreads=n:设置并行收集线程数。 6. -XX:PermSize:表示非堆区初始内存分配大小,其缩写为permanent size(持久化内存)
  6.  -XX:MaxPermSize:表示对非堆区分配的内存的最大上限。

        这里面非常要注意的一点是: 在配置之前一定要慎重的考虑一下自身软件所需要的非堆区内存大小,因为此处内存是不会被java垃圾回收机制进行处理的地方。并且更加要注意的是 最大堆内存与最大非堆内存的和绝对不能够超出操作系统的可用内存一般情况下前者为物理内存的1/64,后者为1/4.

     7. -XX:+CMSClassUnloadingEnabled

相对于并行收集器,CMS收集器默认不会对永久代进行垃圾回收。如果希望对永久代进行垃圾回收,可用设置标志-XX:+CMSClassUnloadingEnabled。在早期JVM版本中,要求设置额外的标志-XX:+CMSPermGenSweepingEnabled。注意,即使没有设置这个标志,一旦永久代耗尽空间也会尝试进行垃圾回收,但是收集不会是并行的,而再一次进行Full GC。

    8.XX:+UseCMSInitiatingOccupancyOnly: 在设置了-XX:+UseCMSInitiatingOccupancyOnly参数的前提下,有三种情况会触发:1、老年代当前使用率是否达到阈值CMSInitiatingOccupancyFraction;2、判断当前新生代的对象是否能够全部顺利的晋升到老年代,如果不能,就提早触发一次老年代的收集。3.如果设置了-XX:+CMSClassUnloadingEnabled,而且_permGen永久带的内存使用率达到了阈值CMSInitiatingPermOccupancyFraction,默认值是92。

调优总结:

  1. 年轻代大小选择
    • 响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象。
    • 吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用。
  2. 年老代大小选择
    • 响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。最优化的方案,一般需要参考以下数据获得: 减少年轻代和年老代花费的时间,一般会提高应用的效率
      • 并发垃圾收集信息
      • 持久代并发收集次数
      • 传统GC信息
      • 花在年轻代和年老代回收上的时间比例
    • 吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。
  3. 较小堆引起的碎片问题
    因为年老代的并发收集器使用标记、清除算法,所以不会对堆进行压缩。当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象。但是,当堆空间较小时,运行一段时间以后,就会出现“碎片”,如果并发收集器找不到足够的空间,那么并发收集器将会停止,然后使用传统的标记、清除方式进行回收。如果出现“碎片”,可能需要进行如下配置:
    • -XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩。
    • -XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩
    • -XX:MaxHeapFreeRatio=30

-XX:MetaspaceSize和-XX:MaxMetaspaceSize

XX:MetaspaceSize=256m这个JVM参数是指Metaspace扩容时触发FullGC的初始化阈值,也是最小的阈值。这里有几个要点需要明确:

  1. 如果没有配置-XX:MetaspaceSize,那么触发FGC的阈值是21807104(约20.8m),可以通过jinfo -flag MetaspaceSize pid得到这个值;
  2. 如果配置了-XX:MetaspaceSize,那么触发FGC的阈值就是配置的值;
  3. Metaspace由于使用不断扩容到-XX:MetaspaceSize参数指定的量,就会发生FGC;且之后每次Metaspace扩容都可能会发生FGC(至于什么时候会,比较复杂,跟几个参数有关);
  4. 如果Old区配置CMS垃圾回收,那么扩容引起的FGC也会使用CMS算法进行回收;
  5. 如果MaxMetaspaceSize设置太小,可能会导致频繁FullGC,甚至OOM;

任何一个JVM参数的默认值可以通过java -XX:+PrintFlagsFinal -version |grep JVMParamName获取,例如:java -XX:+PrintFlagsFinal -version |grep MetaspaceSize

建议:

  1. MetaspaceSizeMaxMetaspaceSize设置一样大;
  2. 具体设置多大,建议稳定运行一段时间后通过jstat -gc pid确认且这个值大一些,对于大部分项目256m即可。

JDK7的PermSize:

JDK8+移除了Perm,引入了Metapsace,它们两者的区别是什么呢?Metasace上面已经总结了,无论-XX:MetaspaceSize-XX:MaxMetaspaceSize两个参数如何设置,随着类加载越来越多不断扩容调整,直到MetaspaceSize(如果没有配置就是默认20.8m)触发FGC,上限是-XX:MaxMetaspaceSize,默认是几乎无穷大。而Perm的话,我们通过配置-XX:PermSize以及-XX:MaxPermSize来控制这块内存的大小,jvm在启动的时候会根据-XX:PermSize初始化分配一块连续的内存块,这样的话,如果-XX:PermSize设置过大,就是一种赤果果的浪费。很明显,Metapsace比Perm好多了;

java -jar -Xmx8192m -Xms8192m -Xmn1024m -XX:MetaspaceSize=1024m -XX:MaxMetaspaceSize=1024m -XX:MaxDirectMemorySize=1024m -XX:SurvivorRatio=10 -XX:+UseG1GC -XX:ParallelGCThreads=4 -XX:ConcGCThreads=4 -XX:+DisableExplicitGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./logs/dump.dump -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -XX:+TraceClassLoading -Xloggc:./logs/gc.log lib/xxx.jar  -args=args

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值