为什么CMS GC时出现Concurrent mode con colsFailure

为什么CMS GC时出现Concurrent Mode Failure_百度知道
为什么CMS GC时出现Concurrent Mode Failure
提问者采纳
&#47.)}&quot.cell&head'&密码&cell&gt:int=0.(@id=&#39.length();cell&quot.{xD i &{xD). compareX可以得到&cell&cell&gt.sheet.row,直接用在控件里设你的XML变量是xData则dataProvider=&&#47.elements(&quot,直接用在控件里设你的XML变量是xData则dataProvider=& i++){/head'姓名&}解析xml [解决办法]楼主想要的可能是一个E4X的表达式;/[解决办法]探讨楼主想要的可能是一个E4X的表达式.row.(@id=')}&quotfor (var i
其他类似问题
cms的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁gc日志含义 - fengbin2005 - ITeye技术网站
博客分类:
新生代gc 日志
Desired survivor size 8716288 bytes, new threshold 7 (max 15)
full gc 日志
1.461: [Full GC (System) [PSYoungGen: 4673K-&0K(59712K)] [PSOldGen: 0K-&K)]
时间为 JVM以启动时间为基准的相对时间
(full 0) 表示 full gc 执行次数
Heap before GC invocations=1
这个1表示gc次数
{Heap before GC invocations=1 (full 0):
PSYoungGen
total 59712K, used 17462K [0x0, 0x0000)
eden space 51200K, 34% used [0xb8,0x0000)
from space 8512K, 0% used [0xa00,0xa0000)
space 8512K, 0% used [0x0,0xa50000)
total 136576K, used 0K [0x0, 0x0000)
object space 136576K, 0% used [0x0,0x0000)
total 65536K, used 9703K [0x000, 0x0000)
object space 65536K, 14% used [0xe60,0x0000)
1.432: [GC
Desired survivor size 8716288 bytes, new threshold 7 (max 15)
[PSYoungGen: 17462K-&K)] 17462K-&K), 0.0258330 secs] [Times: user=0.01 sys=0.00, real=0.03 secs]
Heap after GC invocations=1 (full 0):
PSYoungGen
total 59712K, used 4673K [0x0, 0x0000)
eden space 51200K, 0% used [0x0,0x0000)
from space 8512K, 54% used [0x0,0xa50000)
space 8512K, 0% used [0xa00,0xa0000)
total 136576K, used 0K [0x0, 0x0000)
object space 136576K, 0% used [0x0,0x0000)
total 65536K, used 9703K [0x000, 0x0000)
object space 65536K, 14% used [0xe60,0x0000)
{Heap before GC invocations=2 (full 1):
PSYoungGen
total 59712K, used 4673K [0x0, 0x0000)
eden space 51200K, 0% used [0x0,0x0000)
from space 8512K, 54% used [0x0,0xa50000)
space 8512K, 0% used [0xa00,0xa0000)
total 136576K, used 0K [0x0, 0x0000)
object space 136576K, 0% used [0x0,0x0000)
total 65536K, used 9703K [0x000, 0x0000)
object space 65536K, 14% used [0xe60,0x0000)
1.461: [Full GC (System) [PSYoungGen: 4673K-&0K(59712K)] [PSOldGen: 0K-&K)] 4673K-&K) [PSPermGen: 9703K-&K)], 0.0232110 secs] [Times: user=0.03 sys=0.00, real=0.02 secs]
Heap after GC invocations=2 (full 1):
PSYoungGen
total 59712K, used 0K [0x0, 0x0000)
eden space 51200K, 0% used [0x0,0x0000)
from space 8512K, 0% used [0x0,0xa50000)
space 8512K, 0% used [0xa00,0xa0000)
total 136576K, used 4415K [0x0, 0x0000)
object space 136576K, 3% used [0xff80,0x0000)
total 65536K, used 9703K [0x000, 0x0000)
object space 65536K, 14% used [0xe60,0x0000)
几乎所有的资料上说到打印JVM GC log的时候都会推荐一个参数: -XX:+PrintGCTimeStamps, 可该选项打印的是JVM以启动时间为基准的相对时间,对于troubleshooting来说非常困难。早在07年的时候就有人提出来并且早已fix,用法是使用 PrintGCDateStamps 代替PrintGCTimeStamps,打印出来的就是真实的日期了
服务器参数配置
JAVA_OPTS="-server -Xms200M -Xmx3072M
-XX:PermSize=64M -XX:MaxPermSize=128m -verbose:gc -Xloggc:../logs/gclog.log -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -XX:+HeapDumpOnOutOfMemoryError"
export JAVA_OPTS
---------------------------------------------------------
GC日志分析工具汇总
性能测试排查定位问题,分析调优过程中,会遇到要分析gc日志,人肉分析gc日志有时比较困难,相关图形化或命令行工具可以有效地帮助辅助分析。
Gc日志参数
通过在tomcat启动脚本中添加相关参数生成gc日志
-verbose.gc开关可显示GC的操作内容。打开它,可以显示最忙和最空闲收集行为发生的时间、收集前后的内存大小、收集需要的时间等。
打开-xx:+ printGCdetails开关,可以详细了解GC中的变化。
打开-XX: + PrintGCTimeStamps开关,可以了解这些垃圾收集发生的时间,自JVM启动以后以秒计量。
最后,通过-xx: + PrintHeapAtGC开关了解堆的更详细的信息。
为了了解新域的情况,可以通过-XX:=PrintTenuringDistribution开关了解获得使用期的对象权。
-Xloggc:$CATALINA_BASE/logs/gc.log gc日志产生的路径
XX:+PrintGCApplicationStoppedTime // 输出GC造成应用暂停的时间
-XX:+PrintGCDateStamps // GC发生的时间信息
日志中显示了gc发生的时间,young区回收情况,整体回收情况,fullGC情况,回收所消耗时间等
常用JVM参数
分析gc日志后,经常需要调整jvm内存相关参数,常用参数如下
-Xms:初始堆大小,默认为物理内存的1/64(&1GB);默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制
-Xmx:最大堆大小,默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制
-Xmn:新生代的内存空间大小,注意:此处的大小是(eden+ 2 survivor space)。与jmap -heap中显示的New gen是不同的。整个堆大小=新生代大小 + 老生代大小 + 永久代大小。 在保证堆大小不变的情况下,增大新生代后,将会减小老生代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
-XX:SurvivorRatio:新生代中Eden区域与Survivor区域的容量比值,默认值为8。两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10。
-Xss:每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。应根据应用的线程所需内存大小进行适当调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在左右。一般小的应用, 如果栈不是很深, 应该是128k够用的,大的应用建议使用256k。这个选项对性能影响比较大,需要严格的测试。和threadstacksize选项解释很类似,官方文档似乎没有解释,在论坛中有这样一句话:"-Xss is translated in a VM flag named ThreadStackSize”一般设置这个值就可以了。
-XX:PermSize:设置永久代(perm gen)初始值。默认值为物理内存的1/64。
-XX:MaxPermSize:设置持久代最大值。物理内存的1/4。
Gc日志分析工具
(1)GCHisto
直接点击gchisto.jar就可以运行,点add载入gc.log
统计了总共gc次数,youngGC次数,FullGC次数,次数的百分比,GC消耗的时间,百分比,平均消耗时间,消耗时间最小最大值等
统计的图形化表示
YoungGC,FullGC不同消耗时间上次数的分布图,勾选可以显示youngGC或fullGC单独的分布情况
整个时间过程详细的gc情况,可以对整个过程进行剖析
(2)GCLogViewer
点击run.bat运行
整个过程gc情况的趋势图,还显示了gc类型,吞吐量,平均gc频率,内存变化趋势等
Tools里还能比较不同gc日志
(3)HPjmeter
获取地址 参考文档
工具很强大,但只能打开由以下参数生成的GC log, -verbose:gc -Xloggc:gc.log,添加其他参数生成的gc.log无法打开。
(4)GCViewer
/gcviewer.html
这个工具用的挺多的,但只能在JDK1.5以下的版本中运行,1.6以后没有对应。
(5)garbagecat
其它监控方法
Jvisualvm动态分析jvm内存情况和gc情况,插件:visualGC
jvisualvm还可以heapdump出对应hprof文件(默认存放路径:监控的服务器 /tmp下),利用相关工具,比如HPjmeter可以对其进行分析
grep Full gc.log粗略观察FullGC发生频率
jstat –gcutil [pid] [intervel] [count]
jmap -histo pid可以观测对象的个数和占用空间jmap -heap pid可以观测jvm配置参数,堆内存各区使用情况
jprofiler,jmap dump出来用MAT分析
如果要分析的dump文件很大的话,就需要很多内存,很容易crash。
所以在启动时,我们应该加上一些参数: Java –Xms512M –Xmx1024M –Xss8M
GC Analyzer
Analysis of VerboseGC Traces
http://glezen.org/gca/index.html
支持JDK 1.4.2
支持命令行和界面
PrintGCStats
GC日志分析脚本
/blog/1681347
参考:http://blog.csdn.net/gzh0222/article/details/8223277
---------------------------------------------------
1.原始GC日志(通过JVM配置GC Print参数获取GC日志)
695.775: [GC 695.776: [ParNew: 130944K-&0K(131008K), 0.0174100 secs] 432961K-&6368K), 0.0175930 secs]697.323: [GC [1 CMS-initial-mark: 5360K)] 6368K), 0.1140530 secs]697.438: [CMS-concurrent-mark-start]699.494: [GC 699.494: [ParNew: 130944K-&0K(131008K), 0.0115290 secs] 433654K-&6368K), 0.0116990 secs]701.381: [CMS-concurrent-mark: 1.204/3.944 secs]701.381: [CMS-concurrent-preclean-start]701.382: [CMS-concurrent-preclean: 0.000/0.000 secs]701.420: [CMS-concurrent-abortable-preclean-start]701.420: [CMS-concurrent-abortable-preclean: 0.000/0.000 secs]703.302: [GC 703.302: [ParNew: 130944K-&0K(131008K), 0.0161480 secs] 434835K-&6368K), 0.0163490 secs]705.202: [GC[YG occupancy: 68582 K (131008 K)]705.202: [Rescan (parallel) , 0.1094800 secs]705.312: [weak refs processing, 0.0446420 secs] [1 CMS-remark: 5360K)] 6368K), 0.1543650 secs]705.360: [CMS-concurrent-sweep-start]705.644: [CMS-concurrent-sweep: 0.284/0.284 secs]705.644: [CMS-concurrent-reset-start]705.654: [CMS-concurrent-reset: 0.010/0.010 secs]706.985: [GC 706.985: [ParNew: 130924K-&0K(131008K), 0.0193060 secs] 432106K-&6368K), 0.0195480 secs]708.540: [GC [1 CMS-initial-mark: 5360K)] 6368K), 0.1140590 secs]708.654: [CMS-concurrent-mark-start]710.647: [GC 710.647: [ParNew: 130944K-&0K(131008K), 0.0081390 secs] 433814K-&6368K), 0.0083430 secs]712.560: [CMS-concurrent-mark: 1.314/3.906 secs]712.560: [CMS-concurrent-preclean-start]712.560: [CMS-concurrent-preclean: 0.000/0.000 secs]712.615: [CMS-concurrent-abortable-preclean-start]712.615: [CMS-concurrent-abortable-preclean: 0.000/0.000 secs]713.567: [GC 713.567: [ParNew: 130944K-&0K(131008K), 0.0104890 secs] 434904K-&6368K), 0.0107090 secs]715.109: [GC[YG occupancy: 68948 K (131008 K)]715.109: [Rescan (parallel) , 0.0884690 secs]715.198: [weak refs processing, 0.0441790 secs] [1 CMS-remark: 5360K)] 6368K), 0.1329350 secs]715.243: [CMS-concurrent-sweep-start]715.445: [CMS-concurrent-sweep: 0.203/0.203 secs]715.445: [CMS-concurrent-reset-start]715.454: [CMS-concurrent-reset: 0.009/0.009 secs]
2.日志分析报告
针对原始GC日志,分别用下面两种工具做了分析,其中分析还是比较具体的,就是解析日志时会有些异常,但不影响最后的结果。
(1)通过gcviewer分析:
图1(顶部的黑色线都代表Full GC,也可以理解为Major GC,是根据日志中的CMS GC统计的;底部灰色线代表的是Minor GC)
可以看到Full GC非常多,占所有pause时间比达到65.9%,这是有问题的,GC应该尽可能在年轻代完成,而不是到年老代,这个在第3部分参数说明中会提到。
(2)通过分析:
========================================SUMMARY:========================================# GC Events: 172925GC Event Types: CMS_INITIAL_MARK, CMS_CONCURRENT, CMS_SERIAL_OLD_CONCURRENT_MODE_FAILURE, PAR_NEW, CMS_REMARKMax Heap Space: 1079084KMax Heap Occupancy: 716725KMax Perm Space: 98304KMax Perm Occupancy: 8993KThroughput: 97%Max Pause: 426 msTotal Pause: 9033244 msFirst Timestamp: 250 msLast Timestamp:
从这里主要看pause time时间,分析报告中还有一部分不能处理的,这些日志现在还没找到最终原因:
========================================30 UNIDENTIFIED LOG LINE(S):========================================: [Full GC : [CMS[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor6720]: [Full GC : [CMS[Unloading class sun.reflect.GeneratedMethodAccessor1945]: [Full GC : [CMS (concurrent mode failure)[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor10169]: [Full GC : [CMS (concurrent mode failure)[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor10175]: [Full GC : [CMS[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor33989]: [Full GC : [CMS[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor34622]: [Full GC : [CMS (concurrent mode failure)[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor34638]: [Full GC : [CMS[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor34644]: [Full GC : [CMS[Unloading class sun.reflect.GeneratedMethodAccessor2017]: [Full GC : [CMS[Unloading class sun.reflect.GeneratedMethodAccessor5743]: [Full GC : [CMS[Unloading class sun.reflect.GeneratedMethodAccessor5715]: [Full GC : [CMS[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor58696]: [Full GC : [CMS (concurrent mode failure)[Unloading class sun.reflect.GeneratedMethodAccessor5749]: [Full GC : [CMS[Unloading class sun.reflect.GeneratedMethodAccessor7545]: [Full GC : [CMS (concurrent mode failure)[Unloading class sun.reflect.GeneratedMethodAccessor5806]: [Full GC : [CMS[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor58795]: [Full GC : [CMS[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor58807]: [Full GC : [CMS[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor58817]: [Full GC : [CMS (concurrent mode failure)[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor58821]: [Full GC : [CMS[Unloading class sun.reflect.GeneratedMethodAccessor1643]: [Full GC : [CMS[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor58897]: [Full GC : [CMS (concurrent mode failure)[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor58903]: [Full GC : [CMS[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor81521]: [Full GC : [CMS (concurrent mode failure)[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor81595]: [Full GC : [CMS (concurrent mode failure)[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor81708]: [Full GC : [CMS (concurrent mode failure)[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor81738]: [Full GC : [CMS (concurrent mode failure)[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor81772]: [Full GC : [CMS (concurrent mode failure)[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor81744]: [Full GC : [CMS (concurrent mode failure)[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor81788]: [Full GC : [CMS[Unloading class sun.reflect.GeneratedMethodAccessor10606]
3.问题根源(当前参数配置及说明,其中红色标注的是设置不妥的地方)
98%的java对象,在创建之后不久就变成了非活动对象;只有2%的对象,会在长时间一直处于活动状态。major gc需要的时间比minor gc长的多,所以我们要减少major gc次数,提高minor gc的效率,尽量将非活动对象消灭在年轻代。
针对上述分析报告,从JVM当前参数配置中找到了些原因,如下:
-Xms768m -Xmx1280m
jvm堆的最小值和最大值设置,一般设成相同值,避免频繁分配堆空间
-XX:NewSize=128m -XX:MaxNewSize=128m
年轻代最小值和最大值设置(年轻代设定了,年老代也就定了),也可以用参数-XX:NewRatio=4,年老代和年轻代的大小比,这里128m有点小了,官方建议的是heap的3/8,差不多280m
-XX:PermSize=96m -XX:MaxPermSize=128m 持久代最小值和最大值设置
-XX:MaxTenuringThreshold=0
经过多少次minor gc 后进入年老代,设置为0的话直接进入年老代,这是不太合理的,正常应该在年轻代多呆一段时间,真正需要到年老代的才转过去
-XX:SurvivorRatio=20000
年轻代中eden和一块suvivor区的空间比例,这里设置成20000有问题,suvivor区空间几乎为0,一次minor gc后基本都转到年老代了,年轻代没有起到过滤左右
-XX:+UseParNewGC
年轻代采用并行gc策略,JDK5.0以上,JVM会根据系统配置自行设置,所以无需再设置此值。使用多线程收集,提高吞吐量(-XX:ParallelGCThreads 并行收集器的线程数,此值最好配置与处理器数目相等,如果超过当前cpu数,会加大机器负载)
-XX:+UseConcMarkSweepGC
年老代采用并发gc策略,和应用程序并发执行,减少pause time,但是需要更大的堆区,因为并发执行,有碎片(-XX:+UseParallelOldGC 年老代垃圾收集方式为并行收集,这个是JAVA 6出现的参数选项)
-XX:+CMSPermGenSweepingEnabled
为了避免Perm区满引起的full gc,建议开启CMS回收Perm区选项
-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
打印gc日志
-XX:CMSInitiatingOccupancyFraction=1 年老代使用空间比达到这个值时开始cms gc,默认是在年老代占满68%的时候开始进行CMS收集,这里设置成1是不合理的,会导致CMS GC频繁发生,从gc日志里可以看出来,CMS GC和minor GC几乎一样多
-XX:+CMSIncrementalMode 启动i-CMS模式,增量模式,将cms gc过程分成6个阶段,其中阶段initial Mark和remark时需要pause,这6个阶段在两次minor gc的间隔期执行,具体执行起止时间由下面两个参数决定。拆分成小阶段增量执行时,可以避免应用被中断时间过长,极端情况是如果只有一个cpu,那么得等全部做完这6个阶段才能释放cpu,如果是多cpu这个模式开启与否应该影响不大。
-XX:CMSIncrementalDutyCycleMin=10 默认值10 启动CMS的下线
-XX:CMSIncrementalDutyCycle=30 默认值50 启动CMS的上线
-XX:+UseCMSCompactAtFullCollection
在FULL GC的时候, 对年老代的压缩。CMS是不会移动内存的, 因此这个非常容易产生碎片, 导致内存不够用, 因此, 内存的压缩这个时候就会被启用。 可能会影响性能,但是可以消除碎片,增加这个参数是个好习惯。
-XX:CMSFullGCsBeforeCompaction=0
上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩,这里设置成0不知道什么意思,可以根据线上full gc 的频率确定,频率高,这个值可以大点,比如5,反之频率低,这个值可以小点,比如1
-XX:CMSMarkStackSize=8M
-XX:CMSMarkStackSizeMax=32M
fengbin2005
浏览: 285428 次
那能把加入新的语料后的程序发给我吗
ICTCLAS 这个源码我这边没有的.
第二种情况,维持线程池的数量不变,增大workQueueSiz ...
作者您好,我是一名在校大学生。目前在做中文分词方面的项 ...触发Full&GC执行的情况
除直接调用System.gc外,触发Full GC执行的情况有如下四种。
1. 旧生代空间不足
旧生代空间只有在新生代对象转入及创建为大对象、大数组时才会出现不足的现象,当执行Full GC后空间仍然不足,则抛出如下错误:
java.lang.OutOfMemoryError:&Java&heap&space&
为避免以上两种状况引起的Full
GC,调优时应尽量做到让对象在Minor GC阶段被回收、让对象在新生代多存活一段时间及不要创建过大的对象及数组。
2. Permanet Generation空间满
Generation中存放的为一些class的信息等,当系统中要加载的类、反射的类和调用的方法较多时,Permanet Generation可能会被占满,在未配置为采用CMS GC的情况下会执行Full GC。如果经过Full GC仍然回收不了,那么JVM会抛出如下错误信息:
java.lang.OutOfMemoryError:&PermGen&space&
为避免Perm Gen占满造成Full GC现象,可采用的方法为增大Perm Gen空间或转为使用CMS GC。
3. CMS GCconcurrent mode failure
对于采用CMS进行旧生代GC的程序而言,尤其要注意GC日志中是否有promotion failed和concurrent mode failure两种状况,当这两种状况出现时可能会触发Full GC。
failed是在进行Minor GC时,survivor space放不下、对象只能放入旧生代,而此时旧生代也放不下造成的;concurrent mode failure是在执行CMS GC的过程中同时有对象要放入旧生代,而此时旧生代空间不足造成的。
应对措施为:增大survivor
space、旧生代空间或调低触发并发GC的比率,但在JDK 5.0+、6.0+的版本中有可能会由于JDK的bug29导致CMS在remark完毕后很久才触发sweeping动作。对于这种状况,可通过设置-XX:
CMSMaxAbortablePrecleanTime=5(单位为ms)来避免。
4. 晋升到旧生代的平均大小大于旧生代的剩余空间
这是一个较为复杂的触发情况,Hotspot为了避免由于新生代对象晋升到旧生代导致旧生代空间不足的现象,在进行Minor GC时,做了一个判断,如果之前统计所得到的Minor GC晋升到旧生代的平均大小大于旧生代的剩余空间,那么就直接触发Full GC。
例如程序第一次触发Minor
GC后,有6MB的对象晋升到旧生代,那么当下一次Minor GC发生时,首先检查旧生代的剩余空间是否大于6MB,如果小于6MB,则执行Full GC。
当新生代采用PS
GC时,方式稍有不同,PS GC是在Minor GC后也会检查,例如上面的例子中第一次Minor GC后,PS GC会检查此时旧生代的剩余空间是否大于6MB,如小于,则触发对旧生代的回收。
除了以上4种状况外,对于使用RMI来进行RPC或管理的Sun JDK应用而言,默认情况下会一小时执行一次Full GC。可通过在启动时通过- java
-Dsun.rmi.dgc.client.gcInterval=3600000来设置Full GC执行的间隔时间或通过-XX:+ DisableExplicitGC来禁止RMI调用System.gc。
原文地址:
*对象分配规则
1.对象优先分配在Eden区,如果Eden区没有足够的空间时,虚拟机执行一次Minor&GC。
2.大对象直接进入老年代(大对象是指需要大量连续内存空间的对象)。这样做的目的是避免在Eden区和两个Survivor区之间发生大量的内存拷贝(新生代采用复制算法收集内存)。
3.长期存活的对象进入老年代。虚拟机为每个对象定义了一个年龄计数器,如果对象经过了1次Minor&GC那么对象会进入Survivor区,之后每经过一次Minor&GC那么对象的年龄加1,知道达到阀值对象进入老年区。
4.动态判断对象的年龄。如果Survivor区中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象可以直接进入老年代。
5.空间分配担保。每次进行Minor&GC时,JVM会计算Survivor区移至老年区的对象的平均大小,如果这个值大于老年区的剩余值大小则进行一次Full&GC,如果小于检查HandlePromotionFailure设置,如果true则只进行Monitor&GC,如果false则进行Full&GC。&
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。这个是之前处理过的一个线上问题,处理过程断断续续,经历了两周多的时间,中间各种尝试,总结如下。这篇文章分三部分:
1、问题的场景和处理过程;2、GC的一些理论东西;3、看懂GC的日志
先说一下问题吧
问题场景:线上机器在半夜会推送一个700M左右的数据,这个时候有个数据置换的过程,也就是说有700M*2的数据在heap区域中,线上系统超时比较多,导致了很严重(严重程度就不说了)的问题。
问题原因:看日志,系统接口超时的时候,系统出现了FullGC,这个时候stop-the-world了,也就停机了。分析gc的日志,发现有promotion failed,根据FullGC触发的条件,这个时候就会出现FullGC了。日志如下:
: [ParNew (promotion failed): 1877376K-&77376K),
15.7989680
: [CMS: 2144171K-&46304K),
10.4200280
s] 3514052K-&23680K), [CMS Perm : 119979K-&0132K)],
26.2193500
secs] [Times: user=
问题解决:中间调整过几次,先搞了几台机器做了验证,后来逐步推广的。
1、调大heap区,由原来的4g,调整到5g,young区的大小不变,还是2g,这时候old区就由2g变为3g了(这样保证old区有足够的空间);
2、设置-XX:UseCMSInitiatingOccupancyOnly,其实这个不关这个问题,只是发现半夜CMS进行的有点频繁,就禁止掉了悲观策略;
3、设置CMS区回收的比例,从80%调整到75%,让old区尽早的进行,有足够的空间剩余;
为什么要有GC(垃圾回收)?
JVM通过GC来回收堆和方法区中的内存,GC的基本原理就是找到程序中不再被使用的对象,然后回收掉这些对象占用的内存。
主要的收集器有哪些?
引用计数器和跟踪计数器两种。
引用计数器记录对象是否被引用,当计数器为零时,说明对象已经不再被使用,可以进行回收。java中的对象有复杂的引用关系,不是很适合引用计数器,所以sun jdk中并没有实现这种GC方式。
跟踪收集器,全局记录数据的引用状态,基于一定的条件触发。执行的时候,从根集合开始扫描对象的引用关系,主要有复制(copying)、标记-清除(Mark-Sweep)、标记-压缩(Mark-Compact)那种算法。
跟踪计数器的三种算法简介?
复制:从根集合搜扫描出存活的对象,然后将存活的对象复制到一块新的未使用的空间中,当要回收的空间中存活的对象较少时,比较高效;
标记清除:从根集合开始扫描,对存活的对象进行标记,比较完毕后,再扫描整个空间中未标记的对象,然后进行回收,不需要对对象进行移动;
标记压缩:标记形式和“标记清除”一样,但是回收不存活的对象后,会把所有存活的对象在内存空间中进行移动,好处是减少了内存碎片,缺点是成本比较高;
java内存区域的形式是啥样的?
这里就不再介绍了,之前有一篇文章中专门介绍这个的(
新生代可用的GC?
新生代中对象存活的时间比较短,因此给予Copying算法实现,Eden区域存放新创建的对象,S0和S1区其中一块用于存放在Minor GC的时候作为复制存活对象的目标空间,另外一块清空。
串行GC(Serial GC)比较适合单CPU的情况,可以通过-XX:UseSerialGC来强行制定;
并行回收GC(Parallel Scavenge),启动的时候按照设置的参数来划定Eden/S0/S1区域的大小,但是在运行时,会根据Minor GC的频率、消耗时间来动态调整三个区域的大小,可以用过-XX:UseAdaptiveSizePolicy来固定大小,不进行动态调整;
并行GC(ParNew)划分Eden、S1、S0的区域上和串行GC一样。并行GC需要配合旧生代使用CMS GC(这是他和并行回收GC的不同)(如果配置了CMS GC的方式,那么新生代默认采取的就是并行GC的方式);
啥时候会触发Minor GC?
当Eden区域分配内存时,发现空间不足,JVM就会触发Minor GC,程序中System.gc()也可以来触发。
旧生代可用的GC方式有哪几种?
串行GC(Serial MSC)、并行GC(Parallel MSC)、并发GC(CMS);
采用CMS时候,新生代必须使用Serial GC或者ParNew GC两种。CMS共有七个步骤,只有Initial Marking和Final Marking两个阶段是stop-the-world的,其他步骤均和应用并行进行。持久代的GC也采用CMS,通过-XX:CMSPermGenSweepingEnabled -XX:CMSClassUnloadingEnabled来制定。在采用cms gc的情况下,ygc变慢的原因通常是由于old gen出现了大量的碎片。
为啥CMS会有内存碎片,如何避免?
由于在CMS的回收步骤中,没有对内存进行压缩,所以会有内存碎片出现,CMS提供了一个整理碎片的功能,通过-XX:UseCompactAtFullCollection来启动此功能,启动这个功能后,默认每次执行Full GC的时候会进行整理(也可以通过-XX:CMSFullGCsBeforeCompaction=n来制定多少次Full GC之后来执行整理),整理碎片会stop-the-world.
啥时候会触发CMS GC?
1、旧生代或者持久代已经使用的空间达到设定的百分比时(CMSInitiatingOccupancyFraction这个设置old区,perm区也可以设置);
2、JVM自动触发(JVM的动态策略,也就是悲观策略)(基于之前GC的频率以及旧生代的增长趋势来评估决定什么时候开始执行),如果不希望JVM自行决定,可以通过-XX:UseCMSInitiatingOccupancyOnly=true来制定;
3、设置了 -XX:CMSClassUnloadingE考虑nabled 这个则考虑Perm区;
啥时候会触发Full GC?
一、旧生代空间不足:java.lang.outOfMemoryError:java heap space;
二、Perm空间满:java.lang.outOfMemoryError:PermGen space;
三、CMS GC时出现promotion failed
和concurrent
mode failure(Concurrent mode failure发生的原因一般是CMS正在进行,但是由于old区内存不足,需要尽快回收old区里面的死的java对象,这个时候foreground gc需要被触发,停止所有的java线程,同时终止CMS,直接进行MSC。);
四、统计得到的minor GC晋升到旧生代的平均大小大于旧生代的剩余空间;
五、主动触发Full GC(执行jmap -histo:live [pid])来避免碎片问题;
为啥heap小于3g不建议使用CMS GC这种方式?
毕大师的这篇文章讲的很清楚。
1、触发比例不好设置,设置大了,那么剩余的空间就少了很多,设置小了,那old区还没放置多少东西,就要进行回收了;
2、CMS进行的时候,是并行的,也就意味着如果过于频繁的话,会和应用的强占CPU;
3、CMS会有内存 碎片问题;
4、YGC的速率变慢(由于CMS GC的实现原理,导致对象从新生代晋升到旧生代时,寻找哪里能放下的这个步骤比ParallelOld GC是慢一些的,因此就导致了YGC速度会有一定程度的下降。);
JVM的悲观策略是啥?
所谓的悲观策略(
我们性能测试团队一个同学分析的案例),就是JVM不按照JVM指定的参数来进行CMS GC,而是根据内存情况以及之前回收的方式动态调整,自行进行GC。旧生代剩余的空间(available)大于新生代中使用的空间(max_promotion_in_bytes),或者大于之前平均晋升的old的大小(av_promo),返回false。cms gc是每隔一个周期(默认2s)就会做一次这个检查,如果为false,则不执行YGC,而触发cms gc。
我们经常使用的是啥GC方式?
针对目前线上机器的情况(8G的物流内存),heap区一般设置在4g或者5g左右,一般是使用CMS GC,这时候:
young区使用ParNew(并行GC),Old+Perm(需要单独设置)使用CMS,整个堆(young+old+perm)使用MSC((Mark Sweep Compact)是CMS GC算法的Full GC算法,单线程回收整个堆,回收过程有严格的步骤。压缩,所以回收完理论上任何Generation都不会有内存碎片)压缩回收的方式。
读懂GC日志?
基本上都是这种格式:回收前区域占用的大小-&回收后区域占用的大小(区域设置的大小),占用的时间
1、promotion failed的一段日志
: [ParNew (promotion failed): 1877376K-&77376K),
15.7989680
: [CMS: 2144171K-&46304K),
10.4200280
s] 3514052K-&23680K), [CMS Perm : 119979K-&0132K)],
26.2193500
secs] [Times: user=
解释如下:
1877376K-&77376K),
15.7989680
2144171K-&46304K),
10.4200280
3514052K-&23680K)
heap区情况
119979K-&0132K)],
26.2193500
perm区情况
[Times: user=
整个过程的时间消耗
2、一段正常的CMS的日志
CMS-initial-mark: 46304K)] 23680K),
secs] [Times: user=
: [CMS-concurrent-mark-start]
: [CMS-concurrent-mark:
secs] [Times: user=
: [CMS-concurrent-preclean-start]
: [CMS-concurrent-preclean:
secs] [Times: user=
: [CMS-concurrent-abortable-preclean-start]
CMS: abort preclean due to time
: [CMS-concurrent-abortable-preclean:
secs] [Times: user=
: [GC[YG occupancy:
: [Rescan (parallel) ,
: [weak refs processing,
ss unloading,
: [scrub symbol & string tables,
CMS-remark: 46304K)] 23680K),
secs] [Times: user=
: [CMS-concurrent-sweep-start]
: [CMS-concurrent-sweep:
secs] [Times: user=
: [CMS-concurrent-reset-start]
: [CMS-concurrent-reset:
secs] [Times: user=
这个是一个正常的CMS的日志,共分为七个步骤,重点关注initial-mark和remark这两个阶段,因为这两个是停机的。
A、[GC [1 CMS-initial-mark: 46304K)] 23680K), 0.1390860 secs] [Times: user=0.14 sys=0.00, real=0.14 secs]
各个数据依次表示标记前后old区的所有对象占内存大小和old的capacity,整个JavaHeap(不包括perm)所有对象占内存总的大小和JavaHeap的capacity。
B、T04:00:25.253+.177: [GC[YG occupancy: 573705 K (1877376 K)]: [Rescan (parallel) , 0.3685690 secs]: [weak refs processing, 0.0024100 secs]: [class unloading, 0.0177600 secs]: [scrub symbol & string tables, 0.0154090 secs] [1 CMS-remark: 46304K)] 23680K), 0.4229380 secs] [Times: user=1.41 sys=0.01, real=0.43 secs]
Rescan (parallel)表示的是多线程处理young区和多线程扫描old+perm的卡表的总时间, parallel 表示多GC线程并行。
weak refs processing 处理old区的弱引用的总时间,用于回收native memory。
class unloading 回收SystemDictionary消耗的总时间。
3、一段正常的Young GC的日志
: [ParNew: 1791076K-&77376K),
secs] 2988366K-&23680K),
secs] [Times: user=
ParNew这个表明是并行的回收方式,具体的分别是young区、整个heap区的情况;
4、一段通过system.gc产生的FullGC日志
: [Full GC (System)
: [CMS: 943772K-&220K(2596864K),
secs] 1477000K-&220K(4061184K), [CMS Perm : 3361K-&K)],
secs] [Times: user=
解释如下:
Full GC (System)意味着这是个system.gc调用产生的MSC。
“943772K-&220K(2596864K), 2.3424070 secs”表示:这次MSC前后old区内总对象大小,old的capacity及这次MSC耗时。
“1477000K-&220K(4061184K)”表示:这次MSC前后JavaHeap内总对象大小,JavaHeap的capacity。
“3361K-&K)], 2.3425410 secs”表示:这次MSC前后Perm区内总对象大小,Perm区的capacity。
5、一个特殊的GC日志,根据动态计算直接进行的FullGC(MSC的方式)
: [ParNew: 471872K-&1872K),
: [CMS: 366666K-&4288K),
27.0023450
secs] 838538K-&6160K), [CMS Perm : 3196K-&K)],
27.0025170
ParNew的时间特别短,jvm在minor gc前会首先确认old是不是足够大,如果不够大,这次young gc直接返回,进行MSC。
参考文章:
JVM参数大全
CMS GC不建议3G的原因
毕玄的《分布式java基础》
相关 [cms gc 问题] 推荐:
- ITeye博客
这个是之前处理过的一个线上问题,处理过程断断续续,经历了两周多的时间,中间各种尝试,总结如下. 1、问题的场景和处理过程;2、GC的一些理论东西;3、看懂GC的日志. 问题场景:线上机器在半夜会推送一个700M左右的数据,这个时候有个数据置换的过程,也就是说有700M*2的数据在heap区域中,线上系统超时比较多,导致了很严重(严重程度就不说了)的问题. 问题原因:看日志,系统接口超时的时候,系统出现了FullGC,这个时候stop-the-world了,也就停机了. 分析gc的日志,发现有promotion failed,根据FullGC触发的条件,这个时候就会出现FullGC了. 问题解决:中间调整过几次,先搞了几台机器做了验证,后来逐步推广的.
- 舒の随想日记
某台机器的内存比较大,之前的JVM参数是4G的堆,在压测过程中发现当QPS上来以后,Full GC会开始抬头,YoungGC的频率就不用说了,比较高. 观察GC日志和jstat -gcutil,感觉是QPS在峰值的时候对象创建比较多,也有大对象产生. 于是打算加大堆的大小来延缓GC的时机,并且有一些GC参数的优化,反复调整后找到了一个适合我们的参数(没有一个best的参数,还是得按照应用的的情况去测量,最好是一遍压测一遍调整,最终找到一个best fit的参数组). 在把堆调大的过程中比较担心下面几个问题:. 1、GC的压力会不会增大. 2、一次GC的耗时会不会增加. 3、如果在GC stop-the-world的时间里,rt飙高怎么办.
- Java译站
这篇文章正好接上前一年我们做的一次现实环境下不同GC算法性能比较的试验. 这次我们仍然进行同样的试验,不过增加了对G1回收器的测试,并且在多个平台进行测试. 今年我们测试的垃圾回收器有如下几个:. 我们使用现成的
JIRA任务来运行这个测试. 选择它的原因非常简单——除去Minecraft(一款著名网游),愤怒的小鸟,以及Eclipse不说, JIRA应该是最著名的Java应用程序了. 并且和别的候选者相比,它更能代表我们日常的业务处理流程——毕竟来说Java用得最多的地方还是在服务端的Java企业级应用. 影响我们决定的还有一个因素——
Atlassian的工程师们发布了一个打包好的JIRA压测脚本.
- C++博客-首页原创精华区
通常情况下GC分为两种,分别是:扫描GC(Tracing GC)和引用计数GC(Reference counting GC). 其中扫描GC是比较常用的GC实现方法,其原理是:把正在使用的对象找出来,然后把未被使用的对象释放. 而引用计数GC则是对每个对象都添加一个计数器,引用增加一个计数器就加一,引用减少一个计数器就减一,当计数器减至零时,把对象回收释放. 引用计数GC跟C++中的shared_ptr类似,自然也会存在循环引用问题. 扫描GC(Tracing GC)是广泛使用的GC方法,最简单的实现方式是mark-sweep,即扫描所有存活的对象并mark,然后遍历整个GC对象列表,把所有标记过的对象清除标记,把未标记过的对象释放.
- 码蜂笔记
不同的JVM及其选项会输出不同的日志. 生成下面日志使用的选项:
-XX:+PrintGCTimeStamps
-XX:+PrintGCDetails
-Xloggc:d:/GClogs/tomcat6-gc.log. 最前面的数字
4.445 代表虚拟机启动以来的秒数. [GC 和
[Full GC 是垃圾回收的停顿类型,而不是区分是新生代还是年老代,如果有
Full 说明发生了
Stop-The-World. 如果是调用
System.gc() 触发的,那么将显示的是
[Full GC (System). 接下来的
- loudly - BlueDavy之技术Blog
前两天碰到一个很诡异的GC频繁的现象,走了不少弯路,N种方法查找后才终于查明原因了,在这篇blog中记录下,以便以后碰到这类问题时能更快的解决. 前两天一位同学找到我,说有个应用在启动后就一直Full GC,拿到GC log先看了下,确实是非常的诡异,截取的部分log如下:. 这个日志中诡异的地方在于每次Full GC的时候旧生代都还有很多的空间,于是去看来下启动参数,此时的启动参数如下:. 可以看到,这个启动参数有很多的问题,最重要的在于MaxGCPauseMillis,因为目前版本的jdk其实很难做到达成这个目标,于是猜测可能是这个参数造成的,顺带把启动参数简单修改了下:. 修改完毕,重新启动了一台,发现OK了,于是认为就是这个参数造成的,可惜的是后面又重启了几次后,还是出现了GC频繁的现象.
- 并发编程网 -
Java程序员在编码过程中通常不需要考虑内存问题,JVM经过高度优化的GC机制大部分情况下都能够很好地处理堆(Heap)的清理问题. 以至于许多Java程序员认为,我只需要关心何时创建对象,而回收对象,就交给GC来做吧. 甚至有人说,如果在编程过程中频繁考虑内存问题,是一种退化,这些事情应该交给编译器,交给虚拟机来解决. 这话其实也没有太大问题,的确,大部分场景下关心内存、GC的问题,显得有点“杞人忧天”了,高老爷说过:. 但另一方面,
什么才是“过早优化”. 事实上
JVM的内存模型(
JMM )理应是Java程序员的基础知识,处理过几次JVM线上内存问题之后就会很明显感受到,很多系统问题,都是内存问题.
- Java - 编程语言 - ITeye博客
Java中的GC有哪几种类型. 虚拟机运行在Client模式的默认值,打开此开关参数后,. 使用Serial+Serial Old收集器组合进行垃圾收集. 打开此开关参数后,使用ParNew+Serial Old收集器组合进行垃圾收集. 打开此开关参数后,使用ParNew+CMS+Serial Old收集器组合进行垃圾收集. Serial Old作为CMS收集器出现Concurrent Mode Failure的备用垃圾收集器. 虚拟机运行在Server模式的默认值,打开此开关参数后,使用Parallel Scavenge+Serial Old收集器组合进行垃圾收集. 打开此开关参数后,使用Parallel Scavenge+Parallel Old收集器组合进行垃圾收集.
- 非技术 - ITeye博客
1、引用计数(reference counting).
原理:此对象有一个引用,则+1;删除一个引用,则-1. 缺点:无法处理循环引用的问题. 对象A和B分别有字段b、a,令A.b=B和B.a=A,除此之外这2个对象再无任何引用,那实际上这2个对象已经不可能再被访问,但是引用计数算法却无法回收他们. 2、复制(copying).
原理:把内存空间划分为2个相等的区域,每次只使用一个区域. 垃圾回收时,遍历当前使用区域,把正在使用的对象复制到另外一个区域.
优点:不会出现碎片问题.
缺点:1、暂停整个应用. 3、标记-清扫(Mark-and-sweep)---sun前期版本就是用这个技术.
- Web前端 - ITeye博客
性能测试排查定位问题,分析调优过程中,会遇到要分析gc日志,人肉分析gc日志有时比较困难,相关图形化或命令行工具可以有效地帮助辅助分析. 通过在tomcat启动脚本中添加相关参数生成gc日志. -verbose.gc开关可显示GC的操作内容. 打开它,可以显示最忙和最空闲收集行为发生的时间、收集前后的内存大小、收集需要的时间等. 打开
-xx:+ printGCdetails开关,可以详细了解GC中的变化. 打开
-XX: + PrintGCTimeStamps开关,可以了解这些垃圾收集发生的时间,自JVM启动以后以秒计量. 最后,通过
-xx: + PrintHeapAtGC开关了解堆的更详细的信息.
坚持分享优质有趣的原创文章,并保留作者信息和版权声明,任何问题请联系:@。

我要回帖

更多关于 mode con 的文章

 

随机推荐