堆内存具体的分配和回收步骤:
(1)进入Eden区, 区内存不够的时候就会触发MinorGC,对新生代区进行一次垃圾回收。
(2)MinorGC会清除Eden区的游离对象(没有被GC Roots标记的对象),非垃圾对象(被GC Roots标记的对象)会被复制到SurvivorFrom区,这些对象的分代年龄为1(经历了1次GC)。
(3)Eden内存不够又触发了MinorGC,MinorGC又会和步骤(2)一样清理垃圾,From区也会被清理,没有被清理的对象会被复制到To区,清空Eden区和From区。ServicorTo 和ServicorFrom 互换,原ServivorTo 成为下一次GC 时的ServivorFrom区。
(4)重复(1)(2)(3)步骤如果对象的还没有被清理,分代年龄达15次,该对象就会被复制到老年代。
(5)老年代内存不够时会触发full GC清理整个堆空间—包括年轻代和老年代。会导致STW(stop the world)停止所有用户线程让GC专心回收垃圾,用户线程会出现短暂卡顿。JVM调优就是为了减少STW时间和降低full GC发生次数。
(6)如果full GC后还没有更多的空间放新对象就会发生OOM(内存溢出)。
名词解析:
各个区的内存分配:老年代占三分之二内存,年轻代占三分之一。假如有3Gjvm内存,老年代占2G,年轻代占1G,年轻代中的Eden占800M,Survivor区占200M,Survivor区中的From和To分别占100M。
Eden区:Java 新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老年代)。当Eden 区内存不够的时候就会触发MinorGC,对新生代区进行一次垃圾回收。
SurvivorFrom区:上一次GC 的幸存者,作为这一次GC 的被扫描者。
SurvivorTo区: 保留了一次MinorGC 过程中的幸存者。
MinorGC 的过程:复制->清空->互换
老年代:主要存放应用程序中生命周期长的内存对象。
分代年龄:经历GC的次数
GC Roots:
问:JVM的分代年龄为什么是15?
由对象头里的Mark Word可知,分代年龄为4bit,即最大为1111,即15。