5. JVM 参数详解
5.1 通用 JVM 参数
5.1.1 -server
如果不配置该参数,JVM 会根据应用服务器硬件配置自动选择不同模式,server 模式启动比较慢,但是运行期
速度得到了优化,适合于服务器端运行的 JVM。
5.1.2 -client
启动比较快,但是运行期响应没有 server 模式的优化,适合于个人 PC 的服务开发和测试。
5.5.1.3 -Xmx
设置 java heap 的最大值,默认是机器物理内存的 1/4。这个值决定了最多可用的 Java 堆内存:分配过少就会在
应用中需要大量内存作缓存或者临时对象时出现 OOM(Out Of Memory)的问题;如果分配过大,那么就会因
PermSize 过小而引起的另外一种 Out Of Memory。所以如何配置还是根据运行过程中的分析和计算来确定,如
果不能确定还是采用默认的配置。
5.5.1.4 -Xms
设置 Java 堆初始化时的大小,默认情况是机器物理内存的 1/64。这个主要是根据应用启动时消耗的资源决定,
分配少了申请起来会降低运行速度,分配多了也浪费。
5.1.5 -XX:PermSize
初始化永久内存区域大小。永久内存区域全称是 Permanent Generation space,是指内存的永久保存区域,程序
运行期不对 PermGen space 进行清理,所以如果你的 APP 会 LOAD 很多 CLASS 的话,就很可能出现 PermGen
space错误。这种错误常见在 web 服务器对 JSP 进行 pre compile 的时候。 如果你的 WEB APP 下用了大量的第
三方 jar,其大小超过了 jvm 默认的 PermSize 大小(4M)那么就会产生此错误信息了。
5.1.6 -XX:MaxPermSize
设置永久内存区域最大大小。
5.1.7 -Xmn
直接设置青年代大小。整个 JVM 可用内存大小=青年代大小 + 老年代大小 + 持久代大小 。持久代一般固定
大小为 64m,所以增大年轻代后,将会减小老年代大小。此值对系统性能影响较大,Sun 官方推荐配置为整个堆
的3/8。按照 Sun 的官方设置比例,则上面的例子中年轻代的大小应该为 2048*3/8=768M。
5.1.8 -XX:NewRatio
控制默认的 Young 代的大小,例如,设置-XX:NewRatio=3 意味着 Young 代和老年代的比率是 1:3。换句话说,
Eden 和 Survivor 空间总和是整个堆大小的 1/4。
如图中的实际设置,-XX:NewRatio=2,-Xmx=2048,则年轻代和老年代的分配比例为 1:2,即年轻代的大小为
682M,而老年代的大小为 1365M。查看实际系统的 jvm 监控结果为:
内存池名称: Tenured Gen
Java 虚拟机最初向操作系统请求的内存量: 3,538,944 字节
Java 虚拟机实际能从操作系统获得的内存量: 1,431,699,456 字节
Java 虚拟机可从操作系统获得的最大内存量: 1,431,699,456字节。请注意,并不一定能获得该内存量。
Java 虚拟机此时使用的内存量: 1,408,650,472 字节
即:1,408,650,472 字节*=1365M**,证明了上面的计算是正确的。*
5.1.9 -XX:SurvivorRatio
设置年轻代中 Eden 区与 Survivor 区的大小比值。设置为 4,则两个 Survivor 区与一个 Eden 区的比值为 2:4,
一个 Survivor 区占整个年轻代的 1/6。越大的 survivor 空间可以允许短期对象尽量在年青代消亡;如果 Survivor
空间太小,Copying 收集将直接将其转移到老年代中,这将加快老年代的空间使用速度,引发频繁的完全垃圾回
收。
如下图:
SurvivorRatio 的值设为 3,Xmn 为 768M,则每个 Survivor 空间的大小为 768M/5=153.6M。
5.1.10 -XX:NewSize
为了实现更好的性能,您应该对包含短期存活对象的池的大小进行设置,以使该池中的对象的存活时间不会超
过一个垃圾回收循环。新生成的池的大小由 NewSize 和 MaxNewSize 参数确定。通过这个选项可以设置 Java 新
对象生产堆内存。在通常情况下这个选项的数值为 1024 的整数倍并且大于 1MB。这个值的取值规则为,一般情
况下这个值-XX:NewSize 是最大堆内存(maximum heap size)的四分之一。增加这个选项值的大小是为了增大
较大数量的短生命周期对象。增加 Java 新对象生产堆内存相当于增加了处理器的数目。并且可以并行地分配内
存,但是请注意内存的垃圾回收却是不可以并行处理的。作用跟-XX:NewRatio 相似, -XX:NewRatio 是设置比例
而-XX:NewSize是设置精确的数值。
5.1.11 -XX:MaxNewSize
通过这个选项可以设置最大 Java 新对象生产堆内存。通常情况下这个选项的数值为 1 024 的整数倍并且大于
1MB,其功用与上面的设置新对象生产堆内存-XX:NewSize 相同。一般要将 NewSize 和 MaxNewSize 设成一致。
5.1.12 -XX:MaxTenuringThreshold
设置垃圾最大年龄。如果设置为 0 的话,则年轻代对象不经过 Survivor 区,直接进入老年代。对于老年代比较
多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在 Survivor 区进行多次复制,这样可
以增加对象在年轻代的存活时间,增加在年轻代即被回收的概率。
如下图:
-XX:MaxTenuringThreshold 参数被设置成 5,表示对象会在 Survivor 区进行 5 次复制后如果还没有被回收才会
被复制到老年代。
5.1.13 -XX:GCTimeRatio
设置垃圾回收时间占程序运行时间的百分比。该参数设置为 n 的话,则垃圾回收时间占程序运行时间百分比的
公式为 1/(1+n) ,如果 n=19 表示 java 可以用 5%的时间来做垃圾回收,1/(1+19)=1/20=5%。
5.1.14 -XX:TargetsurvivorRatio
该值是一个百分比,控制允许使用的救助空间的比例,默认值是 50。该参数设置较大的话可提高对 survivor 空
间的使用率。当较大的堆栈使用较低的 SurvivorRatio 时,应增加该值到 80 至 90,以更好利用救助空间。
5.1.15 -Xss
设置每个线程的堆栈大小,根据应用的线程所需内存大小进行调整,在相同物理内存下,减小这个值能生成更
**多的线程。**但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在 3000~5000 左右。当这
个选项被设置的较大(>2MB)时将会在很大程度上降低系统的性能。因此在设置这个值时应该格外小心,调整后
要注意观察系统的性能,不断调整以期达到最优。
JDK5.0 以后每个线程堆栈大小为 1M,以前每个线程堆栈大小为 256K。
5.1.16 -Xnoclassgc
这个选项用来取消系统对特定类的垃圾回收。它可以防止当这个类的所有引用丢失之后,这个类仍被引用时不会
再一次被重新装载,因此这个选项将增大系统堆内存的空间。禁用类垃圾回收,性能会高一点;
5.2 串行收集器参数
5.2.1 -XX:+UseSerialGC:
设置串行收集器 。
5.3 并行收集器参数
5.3.1 -XX:+UseParallelGC:
选择垃圾收集器为并行收集器,此配置仅对年轻代有效,即上述配置下,年轻代使用并行收集,而老年代仍旧
使用串行收集。采用了多线程并行管理和回收垃圾对象,提高了回收效率,提高了服务器的吞吐量,适合于多处理
器的服务器。
5.3.2 -XX:ParallelGCThreads
配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。
5.3.3 -XX:+UseParallelOldGC:
采用对于老年代并发收集的策略,可以提高收集效率。JDK6.0 支持对老年代并行收集。
5.3.4 -XX:MaxGCPauseMillis
设置每次年轻代并行收集最大暂停时间,如果无法满足此时间,JVM 会自动调整年轻代大小以满足此值。
5.3.5 -XX:+UseAdaptiveSizePolicy
设置此选项后,并行收集器会自动选择年轻代区大小和相应的 Survivor 区比例,以达到目标系统规定的最低响应
时间或者收集频率等,此值建议使用并行收集器时,一直打开。
5.4 并发收集器参数
5.4.1 -XX:+UseConcMarkSweepGC
指定在老年代使用 concurrent cmark sweep gc。gc thread 和 app thread 并行(在 init-mark 和 remark 时
pause app thread)。app pause 时间较短 , 适合交互性强的系统 , 如 web server。它可以并发执行收集操作,降
低应用停止时间,同时它也是并行处理模式,可以有效地利用多处理器的系统的多进程处理。
5.4.2 -XX:+UseParNewGC
指定在 New Generation使用 parallel collector, 是 UseParallelGC 的 gc 的升级版本 , 有更好的性能或者优点,可以
和 CMS gc 一起使用
5.4.3 -XX:+UseCMSCompactAtFullCollection**:**
打开对老年代的压缩。可能会影响性能,但是可以消除碎片,在 FULL GC 的时候, 压缩内存, CMS 是不会移
动内存的, 因此这个非常容易产生碎片,导致内存不够用, 因此, 内存的压缩这个时候就会被启用。 增加这个
参数是个好习惯。
5.4.4 -XX:+CMSIncrementalMode
设置为增量模式。适用于单 CPU 情况
5.4.5 -XX:CMSFullGCsBeforeCompaction
由于并发收集器不对内存空间进行压缩、整理,所以运行一段时间以后会产生―碎片‖,使得运行效率降低。此
值设置运行多少次 GC 以后对内存空间进行压缩、整理。
5.4.6 -XX:+CMSClassUnloadingEnabled
使 CMS 收集持久代的类,而不是 fullgc
5.4.7 -XX:+CMSPermGenSweepingEnabled
使 CMS 收集持久代的类,而不是 fullgc。
5.4.8 -XX:-CMSParallelRemarkEnabled
在使用 UseParNewGC 的情况下 , 尽量减少 mark 的时间。
5.4.9 -XX:CMSInitiatingOccupancyFraction
说明老年代到百分之多少满的时候开始执行对老年代的并发垃圾回收(CMS),这个参数设置有很大技巧,基
本上满足公式:(Xmx-Xmn)*(100-CMSInitiatingOccupancyFraction)/100>=Xmn 时就不会出现 promotion
failed。在我的应用中 Xmx 是 6000,Xmn 是 500,那么 Xmx-Xmn 是 5500 兆,也就是老年代有 5500 兆,
CMSInitiatingOccupancyFraction=90 说明老年代到 90%满的时候开始执行对老年代的并发垃圾回收(CMS),
这时还剩 10%的空间是 5500*10%=550 兆,所以即使 Xmn(也就是年轻代共 500 兆)里所有对象都搬到老年代
里,550 兆的空间也足够了,所以只要满足上面的公式,就不会出现垃圾回收时的 promotion failed;如果按照
Xmx=2048,Xmn=768 的比例计算,则 CMSInitiatingOccupancyFraction 的值不能超过 40,否则就容易出现垃圾
回收时的 promotion failed。
5.4.10 -XX:+UseCMSInitiatingOccupancyOnly
指示只有在老年代在使用了初始化的比例后 concurrent collector 启动收集
5.4.11 -XX:SoftRefLRUPolicyMSPerMB
相对于客户端模式的虚拟机(-client 选项),当使用服务器模式的虚拟机时(-server 选项),对于软引用(soft
reference)的清理力度要稍微差一些。可以通过增大-XX:SoftRefLRUPolicyMSPerMB 来降低收集频率。默认值是
1000,也就是说每秒一兆字节。Soft reference 在虚拟机中比在客户集中存活的更长一些。其清除频率可以用命
令行参数 -XX:SoftRefLRUPolicyMSPerMB= 来控制,这可以指定每兆堆空闲空间的 soft reference 保持存活
(一旦它不强可达了)的毫秒数,这意味着每兆堆中的空闲空间中的 soft reference 会(在最后一个强引用被回
收之后)存活 1 秒钟。注意,这是一个近似的值,因为 soft reference 只会在垃圾回收时才会被清除,而垃圾回
收并不总在发生。
5.4.12 -XX:LargePageSizeInBytes
内存页的大小, 不可设置过大,会影响 Perm 的大小。
5.4.13 -XX:+UseFastAccessorMethods
原始类型的快速优化,get,set 方法转成本地代码。
5.4.14 -XX:+DisableExplicitGC
禁止 java 程序中的 full gc, 如 System.gc() 的调用。 最好加上防止程序在代码里误用了,对性能造成冲击。
5.4.15 -XX:+AggressiveHeap
特别说明下:(我感觉对于做 java cache 应用有帮助)
试图是使用大量的物理内存
长时间大内存使用的优化,能检查计算资源(内存, 处理器数量)
至少需要 256MB 内存
大量的 CPU/内存, (在 1.4.1 在 4CPU 的机器上已经显示有提升)
5.4.16 -XX:+AggressiveOpts
加快编译
5.4.17 -XX:+UseBiasedLocking
锁机制的性能改善。