一.堆内存结构模型如图所示:
二.结构模型介绍
1.堆内存分为新生代(Young Generation)与老年代(Old Generation) Y:O=1:3
2.年轻代分为Eden(伊甸园)与Survivor(幸存者),E:S=4:1
3.Survivor区分为大小相同的两个区,From Space与 To Space,F:T=1:1
4.堆内存在Java虚拟机启动时便会创建
三.内存申请过程
1.新创建对象时会在堆内存的Eden中申请一块内存
2.如果Eden中内存空间充足,则直接为新创建的对象分配内存
3.如果Eden中内存不足以再容纳一个新对象时,触发Minor GC
4.Minor GC过程如下:
- ①清除Eden中所有的非活跃对象
- ②若Survivor区的To Space空间不足时,需要将Eden所有对㛑对象象移至老年代中
- ③若Survivor区的To Space空间充足时,将Eden中的活跃对象全部复制到To Space中,并将Eden清空
- ④清除Survivor的From Space内的所有非活跃对象
- ⑤若Survivor区的To Space空间不足时,需要将From Space所有对㛑对象象移至老年代中
- ⑥若Survivor区的To Space空间充足时,将From Space中的活跃对象全部复制到To Space中,并将From Space清空
- ⑦经过MinorGC处理之后,若此时Eden可以容纳新对象,便将新对象存储于Eden中
- ⑧若Eden空间仍不足且From Space空间充足时,在FromSpace中为新对象开辟空间
- ⑨若FromSpace空间仍不足且老年代空间充足时,在老年代为新对象开辟空间
- ⑩若老年代空间不足,则触发Full GC,进行全盘垃圾回收
- ⑪经过Full GC后,若老年代可以容纳新对象,则在老年代为新对象开辟空间
- ⑫相反,抛出异常"Out Of Memory"
四.相关疑问解答:
1.Survivor中的From Space和To Space运作机制是什么?
- ①每次触发MinorGC后,Eden和FromSpace中所有活跃的对象都会被复制到ToSpace中.Eden和FromSpace空间会被清空
- ②这样Eden和FromSpace中的内存都是连续的,不用担心内存碎片的出现
- ③完成复制后,FromSpace和ToSpace交换原本的名称(被清空的总是FromSpace)
- ⑤新生代的内存利用率为90%,因为FromSapce和ToSpace只会有一个工作
2.空间分配担保是什么意思?
- ①MinorGC执行前,会先检查老年代最大可用的连续空间是否足以容纳所有的新生代对象
- ②若可以,此次GC被认为是安全的,MinorGC正常进行
- ③若不可以,JVM会检查HandPromotionFailure设置值(是否允许担保失败)
- ④若HandPromotionFailure=true(允许担保失败),将老年代最大可利用连续空间与历次晋升到老年代中的对象的平均值比较
- 1>若大于,尝试进行一次MinorGC(有风险)
- 2>若小于,进行一次FullGC
- ⑤若HandPromotionFailure=false,进行一次FullGC
总结:之所以这么做是为了避免频繁进行FullGC
3.对象晋升至老年代的时机是什么?
- ①触发MinorGC时,若Eden和Survivor中的活跃对象无法放入到Survivor中,则通过分配担保机制将对象移至老年代
- ②若对象的大小超过-XX:PretenureSizeThreshold设定值时,会绕过新生代而直接在老年代中分配空间
- ③对象在Eden中出生JVM会为其定义一个年龄(age)计数器
- 1>MinorGC执行时对象仍存活,且Survivor中可以容纳该对象,当该对象被移动至Survivor时,age=1
- 2>之后MinorGC时对象若仍存活,则age++
- 3>当age大小超过-XX:MaxTenuringThreshold设定值(默认15)时,对象将进入老年代
- ④上面的说法也不完全对.当Survivor区中相同年龄(currentAge)的对象大小之和超过Survivor空间一半时,Survivor中所有年龄 不小于currentAge的对象全部进入老年代,无需达到-XX:MaxTenuringThreshold设定值