tomcat内存溢出分析网摘

这些文章摘录以备后续跟进处理:

http://globalzhu.iteye.com/blog/853870

http://ldbjakyo.iteye.com/blog/759586

http://www.doc88.com/p-083650830586.html

http://www.importnew.com/1993.html

http://www.importnew.com/2057.html

http://www.importnew.com/3146.html

http://www.importnew.com/3151.html

http://www.tuicool.com/articles/a2yuAz

http://developer.51cto.com/art/201201/312018.htm#CMSInitiatingOccupancyFraction_value

http://hllvm.group.iteye.com/group/topic/38293

http://dasheng.iteye.com/blog/1114639

http://www.oracle.com/technetwork/cn/testcontent/vmoptions-jsp-140102.html

http://blog.sina.com.cn/s/blog_56d8ea9001014de3.html

http://blog.csdn.net/sfdev/article/details/2051171

http://hi.baidu.com/jiangyangw3r/item/402dc1abec3b859e15107383

http://hi.baidu.com/ecspell/item/873de0df10a5a7e4785daaaa

http://william750214.iteye.com/blog/408952

http://blog.csdn.net/sfdev/article/details/2063928

http://blog.sina.com.cn/s/blog_7a35101201016aut.html

http://blog.sina.com.cn/s/blog_7b6fc4c901016uzz.html

http://blog.csdn.net/starxu85/article/details/6403214

http://hongye612430.iteye.com/blog/1326978

http://blog.sina.com.cn/s/blog_7a351012010163a1.html
http://blog.csdn.net/free_xiang/article/details/5790737

摘录:

 探秘Java 7新增垃圾回收器G1特性

下面有一个成熟网站的设计例子:
1:使用bigMemory或者apacheDirectMemory 使用directMemory开辟大内存,规避大heap FullGC问题, 

2:使用G1收集器,我们的hbase RegionServer 也有fullGc问题,使用G1后有明显变化,目前一个月内最多一次full gc . 
  1. -Xmx32g -Xms32g -XX:PermSize=96m -XX:MaxPermSize=96m -XX:+UseG1GC -XX:MaxGCPauseMillis=400 -XX:G1ReservePercent=30 -XX:InitiatingHeapOccupancyPercent=35 -XX:ConcGCThreads=10 -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=1 -XX:GCLogFileSize=50M -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/data/hadoop/logs/gc-hbase-g1.log  

 

 

 使用Java程序从数据库中查询大量的数据时出现异常:java.lang.OutOfMemoryError: Java heap space

在JVM中如果98%的时间是用于GC且可用的 Heap size 不足2%的时候将抛出此异常信息。

JVM堆的设置是指java程序运行过程中JVM可以调配使用的内存空间的设置.JVM在启动的时候会自动设置Heap size的值,其初始空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)是物理内存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置。
例如:java -jar -Xmn16m -Xms64m -Xmx128m MyApp.jar
如果Heap Size设置偏小,除了这些异常信息外,还会发现程序的响应速度变慢了。GC占用了更多的时间,而应用分配到的执行时间较少。
Heap Size 最大不要超过可用物理内存的80%,一般的要将-Xms和-Xmx选项设置为相同,而-Xmn为1/4的-Xmx值。
Heap size的 -Xms -Xmn 设置不要超出物理内存的大小。否则会提示“Error occurred during initialization of VM Could not reserve enough space for object heap”。

这个问题的根源是jvm虚拟机的默认Heap大小是64M,可以通过设置其最大和最小值来实现.设置的方法主要是几个.

1.可以在windows 更改系统环境变量加上JAVA_OPTS=-Xms64m -Xmx512m

2,如果用的tomcat,在windows下,可以在C:\tomcat5.5.9\bin\catalina.bat  中加上:
set JAVA_OPTS=-Xms64m -Xmx256m
位置在: rem Guess CATALINA_HOME if not defined  这行的下面加合适.

3.如果是linux系统
Linux  在{tomcat_home}/bin/catalina.sh的前面,加 set JAVA_OPTS='-Xms64 -Xmx512'

继上次的内存调优分析后(参考[url] http://dmouse.iteye.com/blog/1264118[/url]),gc导致服务器不稳定的情况依然存在,以下记录了后续的调优和分析过程 

目前线上有较多的 "Unloading class sun.reflect.GeneratedSerializationConstructorAccessor"、“promotion failed”、“concurrent mode failure”的错误、 
关于这三个错误产生的原因,可以参考如下文章 
http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html 
http://blogs.oracle.com/jonthecollector/entry/when_the_sum_of_the 
http://blogs.oracle.com/jonthecollector/entry/what_the_heck_s_a 

综上所述,原因大概概括如下: 
1、tenured的预留空间太小 
2、young的一次回收的内存空间太大,以致于tenured无法一次分配连续的内存空间来满足需求 
3、tenured的空闲内存空间不连续,碎片较多 

目前线上系统虽然采用了较多的tenured的空间预留、采用了tenured的内存空间压缩,但仍然不定期的会出现较多的上述三种error,怀疑和设置空间压缩的参数有关 
-XX:CMSFullGCsBeforeCompaction=0 
这个参数,指定进行多少次fullGC之后,进行tenured的内存空间压缩,对 0 的理解认为是每次都会,建议设置为1进行管产 
-XX:CMSFullGCsBeforeCompaction=1 

目前每台服务器的上述三种error记录数如下 
                         "Unloading class" "promotion failed" "concurrent mode failure" 
50----------------------- 2233------------------------8-----------------------------------40 
51 -----------------------2544------------------------15----------------------------------62 
61_CPS----------------2698------------------------21---------------------------------31 
61_CPS2---------------2573-----------------------17---------------------------------40 
62_CPS----------------4815------------------------33---------------------------------47 
62_CPS2--------------3608------------------------29---------------------------------183 



分析内存回收日志,调整了-XX:CMSFullGCsBeforeCompaction=1参数后,回收稳定,无新增的 "Unloading class sun.reflect.GeneratedSerializationConstructorAccessor"、“promotion failed”、“concurrent mode failure”的错误 



在JDK 6的HotSpot VM中,Oracle/Sun有官方支持的GC只有CMS比较特殊:其它几种GC的每个周期都是完全stop-the-world的;而CMS的每个并发GC周期则有两个stop-the-world阶段——initial mark与final re-mark,其它阶段是与应用程序一起并发执行的。 


所以可以通过监控"initial-mark" 和 ‘remark’ 的时间,来反映因为gc导致的程序中断问题 

Java代码   收藏代码
  1. -Xms3g -Xmx3g -Xmn1g -XX:PermSize=128M -XX:+PrintGCDetails -XX:+UseParNewGC -XX:ParallelGCThreads=8 -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=30 -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=1   


按照目前配置,线上环境jvm垃圾回收效率提升,线程中断情况和中断时间明显减少 
-Xms3g -Xmx3g -Xmn1g (堆最大内存 堆最小内存 新生代最大内存) 
1、建议按照系统环境尽量设置合理的值 
2、建议最大内存和最小内存尽量保持一致;jvm会动态分配内存,为了减少内存临时吃紧造成的重新分配开销,提高内存分配的稳定性;-Xms和-Xmx 默认为物理内存的1/64 
3、建议尽量将新生代内存设置为较符合系统的值,避免过小的设置;新生代内存 = eden+ 2 survivor space;Sun官方推荐配置为整个堆的3/8 

-XX:PermSize=128M (永久带内存大小) 
1、存放编译后class对象的地方,默认物理内存的1/64,建议按照系统实际情况设置 

-XX:+PrintGCDetails (打印gc详细信息) 
形式诸如 
[GC [ParNew: 839977K->1563K(943744K), 0.0048690 secs] 994555K->156183K(3040896K), 0.0052340 secs] [Times: user=0.02 sys=0.01, real=0.01 secs] 

[GC [1 CMS-initial-mark: 629255K(2097152K)] 631951K(3040896K), 0.0066920 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[CMS-concurrent-mark: 1.385/1.385 secs] [Times: user=4.80 sys=0.29, real=1.38 secs] 
[CMS-concurrent-preclean: 0.008/0.008 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
[GC [ParNew: 840863K->2737K(943744K), 0.0079350 secs] 1470119K->632187K(3040896K), 0.0084240 secs] [Times: user=0.03 sys=0.01, real= 
0.01 secs] 
[CMS-concurrent-abortable-preclean: 0.646/1.471 secs] [Times: user=2.48 sys=0.27, real=1.47 secs] 
[GC[YG occupancy: 424421 K (943744 K)][Rescan (parallel) , 0.0519000 secs][weak refs processing, 0.0017730 secs] [1 CMS-remark: 6294 
50K(2097152K)] 1053871K(3040896K), 0.0538830 secs] [Times: user=0.32 sys=0.01, real=0.05 secs] 
[CMS-concurrent-sweep: 0.971/0.971 secs] [Times: user=2.06 sys=0.19, real=0.97 secs] 
[CMS-concurrent-reset: 0.012/0.012 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 

具体内容解释详见 http://blogs.oracle.com/poonam/entry/understanding_cms_gc_logs 

-XX:+UseParNewGC -XX:ParallelGCThreads=8 -XX:+UseConcMarkSweepGC (年轻代并行回收 收集器并行8个线程 年老代并发回收) 
1、建议年轻代使用并行回收,同时按照操作系统processer的个数设置并行线程数,理论上<=操作系统processer个数 
2、建议年老代使用并发回收,并发回收以降低中断次数,减少中断时间为目标,适用于对系统响应时间有较高要求的服务 

-XX:CMSInitiatingOccupancyFraction=30 -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=1 
对年老代并发回收的参数优化 
1、 -XX:CMSInitiatingOccupancyFraction=30 
预留足够的空间给young gc,防止从young gc 过来一个较大的内存块,而年老代无足够预留空间,无法提供内存快用于回收后的分配,引起强制的full gc,造成较长时间的线程中断 
2、-XX:+UseCMSCompactAtFullCollection 
设置在FULL GC的时候, 对年老代的压缩;CMS是不会移动内存的, 因此, 这个非常容易产生碎片, 导致内存不够用, 因此, 内存的压缩这个时候就会被启用。 增加这个参数是个好习惯。可能会影响性能,但是可以消除碎片 
3、 -XX:CMSFullGCsBeforeCompaction=1 
设置多少次full gc后进行内存压缩,由于并发收集器不对内存空间进行压缩,整理,所以运行一段时间以后会产生"碎片",使得运行效率降低.此值设置运行多少次GC以后对内存空间进行压缩,整理。

猜你喜欢

转载自jsczxy2.iteye.com/blog/2022666