1. JVM中的年轻代,年老代和持久代区别与联系
JVM中的GC算法采用的是分代收集的策略,即将内存分为几个区域,将不同生命周期的对象放在不同区域里。如下所示:
(1)在GC收集的时候,频繁收集生命周期短的区域(年轻代);
(2)比较少的收集生命周期比较长的区域(年老代);
(3)基本不收集的永久区(持久代)。
年轻代分为1个Eden区和2个Survivor区,新建对象都保存在Survivor区中。当Eden区满则进行Minor GC,将Eden区和一个Survivor区清理到年老代中。这时不能被回收的对象被移动到另一个Survivor区中,保持一个Survivor区是空的。当年老代满时进行Full GC。
2. 堆大小设置
在Java虚拟机中,堆是可供各个线程共享的运行时内存区域,也是供所有类实例和数组对象分配内存的区域。JVM中最大堆大小有3方面限制:相关操作系统的数据模型(32位还是64位)限制;系统可用的虚拟内存限制;系统可用的物理内存限制。在32位操作系统下,一般限制在1.5G-2G,而64位操作系统对内存无限制。
方法一:Java –Xmx3550m –Xms3550m –Xmn2g –Xss128k
(1)-Xmx3550m:最大堆大小。
(2)-Xms3550m:初始堆大小。如果设置与-Xmx相同的值,可以避免每次垃圾回收完成后重新分配JVM的内存。
(3)-Xmn2g:设置年轻代大小为2g。整个JVM内存大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
(4)-Xss128k:设置每个线程的堆栈大小。JDK 5.0后每个线程堆栈大小为1m,以前每个线程堆栈大小为256k。在相同物理内存下,减小这个值能生成更多的线程,但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000-5000左右。
方法二:java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0
(1)-XX:NewRatio=4: 设置年轻代(包括1个Eden和2个Survivor区)与年老代的比值(除去持久代)。设置为4表示年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5。
(2)-XX:SurvivorRatio=4: 设置年轻代中Eden区与Survivor区的大小比值。设置为4表示2个Survivor区与1个Eden区的比值为2:4,1个Survivor区占整个年轻代的1/6。
(3)-XX:MaxPermSize=16m: 设置持久代大小为16m。
(4)-XX:MaxTenuringThreshold=0: 设置垃圾最大年龄。如果设置为0,那么年轻代对象不经过Survivor区,直接进入年老代,这样对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,那么年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概率。
3. 回收器选择
JVM给出了3种回收器选择,分别是:串行收集器,并行收集器,并发收集器。JDK 5.0前都是使用串行收集器,如果想使用其它收集器需要在启动时加入相应的参数。JDK 5.0后,JVM会根据当前系统配置进行判断。
并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔内发生。
(1)只适用于小数据量的串行收集器
(2)吞吐量优先的并行收集器
方法一: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: 配置年老代垃圾收集方式为并行收集。JDK 6.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区比例,以达到目标系统规定的最低响应时间或者收集频率等。使用并行收集器时建议一直打开此值。
说明:并行收集器主要以达到一定的吞吐量为目标,适用于科学技术和后台处理等。
(3)响应时间优先的并发收集器
方法一: java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
-XX:+UseConcMarkSweepGC: 设置年老代为并发收集。配置此项后-XX:NewRatio=4的配置就失效了。所以,此时年轻代大小最好使用-Xmn设置。
-XX:+UseParNewGC: 设置年轻代为并行收集,可与CMS收集同时使用。在JDK 5.0后JVM会根据系统配置自行设置,所以无需再设置此值。
方法二: java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction: 由于并发收集器不对内存空间进行压缩和整理,所以运行一段时间以后会产生“碎片”,使得运行效率降低。此值设置运行多少次GC以后对内存空间进行压缩和整理。
-XX:+UseCMSCompactAtFullCollection: 打开对年老代的压缩。可能会影响性能,但是可以消除碎片。
4. 使用java –X命令查看JVM的配置
自己计算机上的数据,如下所示:
C:\Users\Shengsheng Wang>java -X
-Xmixed 混合模式执行 (默认)
-Xint 仅解释模式执行
-Xbootclasspath: <用 ; 分隔的目录和 zip/jar 文件>
设置搜索路径以引导类和资源
-Xbootclasspath/a:<用 ; 分隔的目录和 zip/jar 文件>
附加在引导类路径末尾
-Xbootclasspath/p:<用 ; 分隔的目录和 zip/jar 文件>
置于引导类路径之前
-Xdiag 显示附加诊断消息
-Xnoclassgc 禁用类垃圾收集
-Xincgc 启用增量垃圾收集
-Xloggc:<file> 将 GC 状态记录在文件中 (带时间戳)
-Xbatch 禁用后台编译
-Xms<size> 设置初始 Java 堆大小
-Xmx<size> 设置最大 Java 堆大小
-Xss<size> 设置 Java 线程堆栈大小
-Xprof 输出 cpu 配置文件数据
-Xfuture 启用最严格的检查, 预期将来的默认值
-Xrs 减少 Java/VM 对操作系统信号的使用 (请参阅文档)
-Xcheck:jni 对 JNI 函数执行其他检查
-Xshare:off 不尝试使用共享类数据
-Xshare:auto 在可能的情况下使用共享类数据 (默认)
-Xshare:on 要求使用共享类数据, 否则将失败。
-XshowSettings 显示所有设置并继续
-XshowSettings:all 显示所有设置并继续
-XshowSettings:vm 显示所有与 vm 相关的设置并继续
-XshowSettings:properties 显示所有属性设置并继续
-XshowSettings:locale 显示所有与区域设置相关的设置并继续
说明:所有的相关参数都可以使用java和javac来查看。
5. 常见配置汇总
(1)堆设置
-Xms:初始堆大小。
-Xmx:最大堆大小。
-XX:NewSize=n:设置年轻代大小。
-XX:NewRatio=n:设置年轻代和年老代的比值。
-XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。-XX:MaxPermSize=n:设置持久代大小。
(2)收集器设置
-XX:+UseSerialGC:设置串行收集器。
-XX:+UseParallelGC:设置并行收集器。
-XX:+UseParalledlOldGC:设置并行年老代收集器。
-XX:+UseConcMarkSweepGC:设置并发收集器。
(3)垃圾回收统计信息
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:filename
(4)并行收集器设置
-XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数,即并行收集线程数。
-XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间。
-XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)。
(5)并发收集器设置
-XX:+CMSIncrementalMode:设置为增量模式,适用于单CPU情况。
-XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数,即并行收集线程数。
参考文献:
[1] Java虚拟机(JVM)参数配置说明:http://lavasoft.blog.51cto.com/62575/25492/
[2] JVM调优总结:http://www.cnblogs.com/likehua/p/3369823.html
[3] Java GC日志解析:http://jingyan.baidu.com/article/3ea51489c045d852e61bbaab.html
[4] Java虚拟机中的新生代与老年代:http://my.oschina.net/sunnywu/blog/332870
[5] JVM介绍:http://www.cnblogs.com/sunada2005/p/3577799.html