经过JVM的这些选项:Xms/Xmx/PermSize/MaxPermSize能够牵扯出不少问题,好比性能调优等。html
说明:如下转载没通过实践。java
经验实例(参考):web
设置每一个线程的堆栈大小。JDK5.0之后每一个线程堆栈大小为1M,之前每一个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减少这个值能生成更多的线程。可是操做系统对一个进程内的线程数仍是有限制的,不能无限生成,经验值在3000~5000左右。算法
参数的含义:数组
VM内存管理的机制:缓存
一、堆(Heap)和非堆(Non-heap)内存服务器
按照官方的说法:“Java虚拟机具备一个堆,堆是运行时数据区域,全部类实例和数组的内存均今后处分配。堆是在Java虚拟机启动时建立的。”,“在JVM中堆以外的内存称为非堆内存(Non-heap memory)”。并发
能够看出JVM主要管理两种类型的内存:堆和非堆。简单来讲堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给本身用的,因此方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每一个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码都在非堆内存中。 app
1.一、堆内存分配eclipse
JVM初始分配的堆内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的堆内存由-Xmx指定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;
空余堆内存大于70%时,JVM会减小堆直到-Xms的最小限制。所以服务器通常设置-Xms、-Xmx 相等以免在每次GC 后调整堆的大小。
说明:若是-Xmx不指定或者指定偏小,应用可能会致使java.lang.OutOfMemory错误,此错误来自JVM,不是Throwable的,没法用try...catch捕捉。
1.二、非堆内存分配
JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。(还有一说:MaxPermSize缺省值和-server -client选项相关,-server选项下默认MaxPermSize为64m,-client选项下默认MaxPermSize为32m。这个我没有实验。)
上面错误信息中的PermGen space的全称是Permanent Generation space,是指内存的永久保存区域。尚未弄明白PermGen space是属于非堆内存,仍是就是非堆内存,但至少是属于了。
XX:MaxPermSize设置太小会致使java.lang.OutOfMemoryError: PermGen space 就是内存益出。
说说为何会内存益出:
二、JVM内存限制(最大值)
首先JVM内存限制于实际的最大物理内存,假设物理内存无限大的话,JVM内存的最大值跟操做系统有很大的关系。简单的说就32位处理器虽然可控内存空间有4GB,可是具体的操做系统会给一个限制,这个限制通常是2GB-3GB(通常来讲Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制了。
为何有的机器我将-Xmx和-XX:MaxPermSize都设置为512M以后Eclipse能够启动,而有些机器没法启动?
经过上面对JVM内存管理的介绍咱们已经了解到JVM内存包含两种:堆内存和非堆内存,另外JVM最大内存首先取决于实际的物理内存和操做系统。因此说设置VM参数致使程序没法启动主要有如下几种缘由:
三、堆大小设置
JVM 中最大堆大小有三方面限制:相关操做系统的数据模型(32-bt仍是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制。32位系统下,通常限制在1.5G~2G;64为操做系统对内存无限制。我在Windows Server 2003系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m。
3.一、典型设置:
3.1.一、java -Xmx3550m -Xms3550m -Xmn2g-Xss128k
3.1.二、java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0
四、回收器选择
JVM给了三种选择:串行收集器、并行收集器、并发收集器,可是串行收集器只适用于小数据量的状况,因此这里的选择主要针对并行收集器和并发收集器。默认状况下,JDK5.0之前都是使用串行收集器,若是想使用其余收集器须要在启动时加入相应参数。JDK5.0之后,JVM会根据当前系统配置进行判断。
4.一、吞吐量优先的并行收集器
如上文所述,并行收集器主要以到达必定的吞吐量为目标,适用于科学技术和后台处理等。
4.1.一、典型配置:
4.1.1.一、java -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20
4.1.1.二、java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC
4.1.1.三、java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis=100
4.1.1.四、java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis=100 -XX:+UseAdaptiveSizePolicy
4.二、响应时间优先的并发收集器
如上文所述,并发收集器主要是保证系统的响应时间,减小垃圾收集时的停顿时间。适用于应用服务器、电信领域等。
4.2.一、典型配置:
4.2.1.一、java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
4.2.1.二、java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection
4.三、辅助信息
JVM提供了大量命令行参数,打印信息,供调试使用。主要有如下一些:
4.3.一、-XX:+PrintGC
输出形式:
[GC 118250K->113543K(130112K), 0.0094143 secs]
[Full GC 121376K->10414K(130112K), 0.0650971 secs]
4.3.二、-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]
4.3.三、-XX:+PrintGCTimeStamps -XX:+PrintGC:PrintGCTimeStamps可与上面两个混合使用
输出形式:
11.851: [GC 98328K->93620K(130112K), 0.0082960 secs]
4.3.四、-XX:+PrintGCApplicationConcurrentTime:打印每次垃圾回收前,程序未中断的执行时间。可与上面混合使用
输出形式:
Application time: 0.5291524 seconds
4.3.五、-XX:+PrintGCApplicationStoppedTime:打印垃圾回收期间程序暂停的时间。可与上面混合使用
输出形式:
Total time for which application threads were stopped: 0.0468229 seconds
4.3.六、-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]
4.3.七、-Xloggc:filename:与上面几个配合使用,把相关日志信息记录到文件以便分析。
五、常见配置汇总
5.一、堆设置
5.二、收集器设置
5.三、垃圾回收统计信息
5.四、并行收集器设置
5.五、并发收集器设置
六、调优总结
6.一、年轻代大小选择
6.二、年老代大小选择
6.2.一、响应时间优先的应用:年老代使用并发收集器,因此其大小须要当心设置,通常要考虑并发会话率和会话持续时间等一些参数。若是堆设置小了,能够会形成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;若是堆大了,则须要较长的收集时间。最优化的方案,通常须要参考如下数据得到:
减小年轻代和年老代花费的时间,通常会提升应用的效率。
6.2.二、吞吐量优先的应用:通常吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。缘由是,这样能够尽量回收掉大部分短时间对象,减小中期的对象,而年老代尽存放长期存活对象。
6.三、较小堆引发的碎片问题
由于年老代的并发收集器使用标记、清除算法,因此不会对堆进行压缩。当收集器回收时,他会把相邻的空间进行合并,这样能够分配给较大的对象。可是,当堆空间较小时,运行一段时间之后,就会出现“碎片”,若是并发收集器找不到足够的空间,那么并发收集器将会中止,而后使用传统的标记、清除方式进行回收。若是出现“碎片”,可能须要进行以下配置:
七、调优实例
环境LinuxAS4,resin2.1.17,JDK6.0,2CPU,4G内存,dell2950服务器。
7.一、JVM调优之串行垃圾回收
也就是默认配置,完成10万request用时153秒。JVM参数配置以下:
$JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server
-Xms2048M-Xmx2048M-Xmn512M
-XX:PermSize=256M-XX:MaxPermSize=256M
-XX:MaxTenuringThreshold=7-XX:GCTimeRatio=19
-Xnoclassgc-Xloggc:log/gc.log
-XX:+PrintGCDetails-XX:+PrintGCTimeStamps";
这种配置通常在resin启动24小时内彷佛没有大问题,网站能够正常访问,但查看日志发现,在接近24小时时,FullGC执行愈来愈频繁,大约每隔3分钟就有一次FullGC,每次FullGC系统会停顿6秒左右,做为一个网站来讲,用户等待6秒恐怕太长了,因此这种方式有待改善。MaxTenuringThreshold=7表示一个对象若是在救助空间移动7次尚未被回收就放入年老代,GCTimeRatio=19表示java能够用5%的时间来作垃圾回收,1/(1+19)=1/20=5%。
7.二、JVM调优之并行回收
完成10万request用时117秒,配置以下:
$JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server-Xmx2048M
-Xms2048M-Xmn512M-XX:PermSize=256M-XX:MaxPermSize=256M
-Xnoclassgc-Xloggc:log/gc.log-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps-XX:+UseParallelGC-XX:ParallelGCThreads=20
-XX:+UseParallelOldGC-XX:MaxGCPauseMillis=500
-XX:+UseAdaptiveSizePolicy-XX:MaxTenuringThreshold=7
-XX:GCTimeRatio=19";
并行回收我尝试过多种组合配置,彷佛都没什么用,resin启动3小时左右就会停顿,时间超过10秒。也有多是参数设置不够好的缘由,MaxGCPauseMillis表示GC最大停顿时间,在resin刚启动尚未执行FullGC时系统是正常的,但一旦执行FullGC,MaxGCPauseMillis根本没有用,停顿时间可能超过20秒,以后会发生什么我也再也不关心了,赶忙重启resin,尝试其余回收策略。
7.三、JVM调优之并发回收
完成10万request用时60秒,比并行回收差很少快一倍,是默认回收策略性能的2.5倍,配置以下:
$JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server
-Xms2048M-Xmx2048M-Xmn512M-XX:PermSize=256M
-XX:MaxPermSize=256M-XX:+UseConcMarkSweepGC
-XX:MaxTenuringThreshold=7-XX:GCTimeRatio=19
-Xnoclassgc-Xloggc:log/gc.log-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0";
这个配置虽然不会出现10秒连不上的状况,但系统重启3个小时左右,每隔几分钟就会有5秒连不上的状况,查看gc.log,发如今执行ParNewGC时有个promotionfailed错误,从而转向执行FullGC,形成系统停顿,并且会很频繁,每隔几分钟就有一次,因此还得改善。UseCMSCompactAtFullCollection是表是执行FullGC后对内存进行整理压缩,省得产生内存碎片,CMSFullGCsBeforeCompaction=N表示执行N次FullGC后执行内存压缩。
7.四、JVM调优之增量回收
完成10万request用时171秒,太慢了,配置以下:
$JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server
-Xms2048M-Xmx2048M-Xmn512M-XX:PermSize=256M
-XX:MaxPermSize=256M-XX:MaxTenuringThreshold=7
-XX:GCTimeRatio=19-Xnoclassgc-Xloggc:log/gc.log
-XX:+PrintGCDetails-XX:+PrintGCTimeStamps-Xincgc";
彷佛回收得也不太干净,并且也对性能有较大影响,不值得试。
7.五、JVM调优之并发回收的I-CMS模式
和增量回收差很少,完成10万request用时170秒。配置以下:
$JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server
-Xms2048M-Xmx2048M-Xmn512M-XX:PermSize=256M
-XX:MaxPermSize=256M-XX:MaxTenuringThreshold=7
-XX:GCTimeRatio=19-Xnoclassgc-Xloggc:log/gc.log
-XX:+PrintGCDetails-XX:+PrintGCTimeStamps
-XX:+UseConcMarkSweepGC-XX:+CMSIncrementalMode
-XX:+CMSIncrementalPacing
-XX:CMSIncrementalDutyCycleMin=0
-XX:CMSIncrementalDutyCycle=10-XX:-TraceClassUnloading";
采用了sun推荐的参数,回收效果很差,照样有停顿,数小时以内就会频繁出现停顿,什么sun推荐的参数,照样很差使。
7.六、JVM调优之递增式低暂停收集器
又叫什么火车式回收,完成10万request用时153秒,配置以下:
$JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server
-Xms2048M-Xmx2048M-Xmn512M-XX:PermSize=256M
-XX:MaxPermSize=256M-XX:MaxTenuringThreshold=7
-XX:GCTimeRatio=19-Xnoclassgc-Xloggc:log/gc.log
-XX:+PrintGCDetails-XX:+PrintGCTimeStamps-XX:+UseTrainGC";
该配置效果也很差,影响性能,因此没试。
7.七、相比之下,仍是并发回收比较好,性能比较高,只要能解决ParNewGC(并行回收年轻代)时的promotionfailed错误就一切好办了,查了不少文章,发现引发promotionfailed错误的缘由是CMS来不及回收(CMS默认在年老代占到90%左右才会执行),年老代又没有足够的空间供GC把一些活的对象从年轻代移到年老代,因此执行FullGC。CMSInitiatingOccupancyFraction=70表示年老代占到约70%时就开始执行CMS,这样就不会出现FullGC了。SoftRefLRUPolicyMSPerMB这个参数也是我认为比较有用的,我以为不必等1秒,因此设置成0。配置以下
$JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server-Xms2048M
-Xmx2048M-Xmn512M-XX:PermSize=256M-XX:MaxPermSize=256M
-XX:SurvivorRatio=8-XX:MaxTenuringThreshold=7
-XX:GCTimeRatio=19-Xnoclassgc-XX:+DisableExplicitGC
-XX:+UseParNewGC-XX:+UseConcMarkSweepGC
-XX:+CMSPermGenSweepingEnabled
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0
-XX:+CMSClassUnloadingEnabled-XX:-CMSParallelRemarkEnabled
-XX:CMSInitiatingOccupancyFraction=70
-XX:SoftRefLRUPolicyMSPerMB=0-XX:+PrintClassHistogram
-XX:+PrintGCDetails-XX:+PrintGCTimeStamps
-XX:+PrintGCApplicationConcurrentTime
-XX:+PrintGCApplicationStoppedTime
-Xloggc:log/gc.log";
上面这个配置内存上升的很慢,24小时以内几乎没有停顿现象,最长的只停滞了0.8s,ParNewGC每30秒左右才执行一次,每次回收约0.2秒,看来问题应该暂时解决了。
参数不明白的能够上网查,本人认为比较重要的几个参数是:
-Xms-Xmx-XmnMaxTenuringThresholdGCTimeRatioUse ConcMarkSweepGCCMSInitiatingOccupancyFractionSoftRefLRUPolicyMSPerMB eclipse中配置JVM参数:-Xmx1024M-Xms1000M-server-XX:PermSize=64M-XX:MaxPermSize=128m
参考:
http://technique-digest.iteye.com/blog/1123046(以上内容部分转自此篇文章)
http://www.360doc.com/content/15/0330/12/16782314_459269672.shtml(以上部份内容转自此篇文章)
http://www.51testing.com/html/80/n-862780.html(JVM的参数调优,解决GC回收时卡顿的问题)
http://www.importnew.com/15934.html(为何JVM指定-Xmx参数后占用内存会变少?)
http://www.cnblogs.com/chengxin1982/p/3818448.html
http://unixboy.iteye.com/blog/174173(以上内容部分转自此篇文章)
http://www.cnblogs.com/koik/p/4452029.html
http://cxh61207.iteye.com/blog/1160663
http://blog.chinaunix.net/uid-26602509-id-4110150.html(Tomcat内存调优)
http://blog.csdn.net/zhushuai1221/article/details/51027024
http://developer.51cto.com/art/201201/312639.htm(调优专题频道)
http://developer.51cto.com/art/201009/227848_all.htm(JVM调优实例,以上部份内容转自此篇文章)
http://www.cnblogs.com/zhguang/p/Java-JVM-GC.html
http://uule.iteye.com/blog/2114697