垃圾回收从新生代进入老年代
2021-12-01 18:04:13 0 举报
垃圾回收从新生代进入老年代
作者其他创作
大纲/内容
Eden区:8
Java堆内存-Xms-Xmx
一、初始标记(CMS initial mark):仅标记一下GC Roots能直接关联到的对象;速度很快;但需要\"Stop The World\"(方法的局部变量和类的静态变量是GC Roots)。二、并发标记(CMS concurrent mark):进行GC Roots Tracing的过程;刚才产生的集合中标记出存活对象;应用程序也在运行;并不能保证可以标记出所有的存活对象(对老年代里的全部对象,进行GC Roots追踪,看看它被谁引用了,最耗时)。三、重新标记(CMS remark):为了修正并发标记期间因用户程序继续运作而导致标记变动的那一部分对象的标记记录或新生成的对象;需要\"Stop The World\",且停顿时间比初始标记稍长,但远比并发标记短;采用多线程并行执行来提升效率(重新标记下在第二阶段里新创建的一些对象,还有一些已有对象可能失去引用变成垃圾的情况)。四、并发清除(CMS concurrent sweep):回收所有的垃圾对象。
永久代-XX:PermSize-XX:MaxPermSize
线程2
线程虚拟机栈-Xss
线程1
当Eden内存快满时标记存活对象复制到from
ParNew垃圾回收器-XX:ParallelGCThreads(并发线程数)
Serial垃圾回收器
15次GC存活对象
-XX:MaxTenuringThreshold=15
单线程
Full GC(Major GC或Old GC)
CMS垃圾回收器
当Eden和from均满后,触发MinorGC,将两块内存存活对象复制到to
Minor GC
垃圾回收算法(标记清理算法)
新生代-Xmn
垃圾回收算法(复制清除算法)
Full GC
Survivor1:1to
老年代内存空间小于了历次Minor GC后升入老年代对象的平均大小,判断Minor GC有风险,可能就会提前触发Full GC回收老年代的垃圾对象。或者是一次Minor GC后的对象太多了,都要升入老年代,发现空间不足,出发了一次老年代的Full GC。当老年代内存占用达到一定比例了,就自动执行GC。“-XX:CMSInitiatingOccupancyFaction”参数可以用来设置老年代占用多少比例的时候触发CMS垃圾回收,JDK 1.6里面默认的值是92%。CMS默认启动的垃圾回收线程的数量是(CPU核数 + 3)/ 4
老年代
JVM
Stop the World
如果CMS垃圾回收期间,系统程序要放入老年代的对象大于了可用内存空间,此时会如何?这个时候,会发生Concurrent Mode Failure,就是说并发垃圾回收失败了,我一边回收,你一边把对象放入老年代,内存都不够了。此时就会自动用“Serial Old”垃圾回收器替代CMS,就是直接强行把系统程序“Stop the World”,重新进行长时间的GC Roots追踪,标记出来全部垃圾对象,不允许新的对象产生然后一次性把垃圾对象都回收掉,完事儿了再恢复系统线程。所以在生产实践中,这个自动触发CMS垃圾回收的比例需要合理优化一下,避免“Concurrent Mode Failure”问题。CMS有一个参数是“-XX:+UseCMSCompactAtFullCollection”,默认就打开了,意思是在Full GC之后要再次进行“Stop the World”,停止工作线程,然后进行碎片整理,就是把存活对象挪到一起,空出来大片连续内存空间,避免内存碎片。还有一个参数是“-XX:CMSFullGCsBeforeCompaction”,这个意思是执行多少次Full GC之后再执行一次内存碎片整理的工作,默认是0,意思就是每次Full GC之后都会进行一次内存整理。
1.存活对象总大小超过Survivor的50%2.大对象(-XX:PretenureSizeThreshold)3.Eden存活对象大于Survivor内存4.MinorGC后存活大小超过老年代可用内存,(-XX:-HandlePromotionFailure)触发一次Full GC,回收老年代,再执行MinorGC:一此时Survivor空间足够直接进入;二Survivor空间还是不足,直接进入老年代;三如果老年代空间不足,则触发Full GC腾出空间,如果还是不够,则出现OOM内存溢出
Survivor0:1from
0 条评论
回复 删除
下一页