先描述一下Java堆内存划分,再解释Minor GC,Major GC,full GC,描述它们之间转化流程。(此文针对jdk8)
目录
1.内存结构
GC通常是发生在堆上,堆上GC的内存结构如下:
默认 -XX:NewRatio=2 , 标识新生代占1 , 老年代占2 ,新生代占整个堆的1/3.
修改占比 -XX:NewPatio=4 , 标识新生代占1 , 老年代占4 , 新生代占整个堆的1/5.
Eden空间和另外两个Survivor空间占比分别为8:1:1.
可以通过操作选项 -XX:SurvivorRatio 调整这个空间比例。 比如 -XX:SurvivorRatio=8.
几乎所有的java对象都在Eden区创建, 但80%的对象生命周期都很短,创建出来就会被销毁.
2.堆GC触发条件
垃圾收集器
Java 中的堆也是 GC 收集垃圾的主要区域。GC 分为两种:一种是部分收集器(Partial GC)另一类是整堆收集器(Fu'll GC).
部分收集器: 不是完整收集java堆的的收集器,它又分为:
- 新生代收集(Minor GC / Young GC): 只是新生代的垃圾收集.
- 老年代收集 (Major GC / Old GC): 只是老年代的垃圾收集 (CMS GC 单独回收老年代).
- 混合收集(Mixed GC):收集整个新生代及老年代的垃圾收集 (G1 GC会混合回收, region区域回收) .
整堆收集(Full GC):收集整个java堆和方法区的垃圾收集器.
年轻代GC触发条件
- 年轻代空间不足,就会触发Minor GC, 这里年轻代指的是Eden代满,Survivor不满不会引发GC.
- Minor GC会引发STW(stop the world) ,暂停其他用户的线程,等垃圾回收接收,用户的线程才恢复.
老年代GC (Major GC)触发机制
- 老年代空间不足时,会尝试触发MinorGC. 如果空间还是不足,则触发Major GC.
- 如果Major GC , 内存仍然不足,则报错OOM.
- Major GC的速度比Minor GC慢10倍以上.
FullGC 触发机制
- 调用System.gc() , 系统会执行Full GC ,不是立即执行.
- 老年代空间不足.
- 方法区空间不足.
- 通过Minor GC进入老年代平均大小大于老年代可用内存
3.GC的过程描述
通过上述1,2步骤已经知道在堆上GC的区域,和触发的条件,整体描述下如下:
- 当 Eden 区的空间满了, Java虚拟机会触发一次 Minor GC,以收集新生代的垃圾,存活下来的对象,则会转移到 Survivor区。
- 大对象(需要大量连续内存空间的Java对象,如那种很长的字符串)直接进入老年态;
- 如果对象在Eden出生,并经过第一次Minor GC后仍然存活,并且被Survivor容纳的话,年龄设为1,每熬过一次Minor GC,年龄+1,若年龄超过一定限制(15),则被晋升到老年态。即长期存活的对象进入老年态。
- Major GC 发生在老年代的GC,清理老年区,经常会伴随至少一次Minor GC,比Minor GC慢10倍以上。
- 老年代满了而无法容纳更多的对象,Minor GC 之后通常就会进行Full GC,Full GC 清理整个内存。