内存分配与回收策略
仅作为笔记
前言
仅作为笔记
一、内存分配与回收策略
1.1 对象优先在Eden分配
- 在大多数情况下,对象分配在新生代的Eden区,当Eden区没有足够的内存空间时会触发一次Minor GC(新生代垃圾回收)。
下面解释一些概念:
- GC:垃圾回收,在jvm中的含义为回收无用内存空间
- Young space:新生代,由分代GC概念划分而来,保存生命周期较短的对象
- Tenured space:年老代,由分代GC概念划分而来,保存生命周期较长的对象
- Minor GC:发生在新生代中的gc
- Major GC:发生在老年代gc
- stop the world:指的是用户线程在运行至安全点(safe point)或安全区域(safe region)之后,就自行挂起,进入暂停状态,对外的表现看起来就像是全世界都停止运转了一样,而不论何种gc算法都会stop the world,区别只在于stop the world的时间长短。
- Full GC:在通常意义上说的Full GC为一次特殊GC行为的描述,这次GC会回收整个堆的内存,包含老年代,新生代,metaspace等。
1.2 大对象直接进入老年代
- 指需要大量连续内存空间的Java对象,最典型的就是很长的字符串以及数组,大对象对虚拟机的内存分配很不友好。经常出现大对象容易导致内存还有不少的时候就提前触发垃圾收集,这样会影响整个系统的性能。
1.3 长期存活的对象将进入老年代
- 虚拟机给每个对象定义了一个对象年龄(Age)计数器。如果对象在Eden出生并经过第一次Minor GC后仍然存活,并且能被Survivor容纳的话,将被移动到Survivor空间中,并且对象年龄设为1。对象在Survivor区中每“熬过”一次Minor GC,年龄就增加1岁,当它的年龄增加到一定程度(默认为15岁),就将会被晋升到老年代中。
1.4 动态对象年龄判定
- 另一种判断对象是否可以进入老年代的条件:
如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等MaxTenuringThreshold中要求的年龄。
1.5 空间分配担保
- 在发生Minor
GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果这个条件成立,那么Minor GC可以确保是安全的。如果不成立,则虚拟机会查看 HandlePromotionFailure设置值是否允许担保失败。如果允许,那么会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试着进行一次Minor GC,尽管这次Minor GC是有风险的;如果小于,或者HandlePromotionFailure设置不允许冒险,那这时也要改为进行一次Full GC。
注意:虽然担保失败时绕的圈子是最大的,但大部分情况下都还是会将HandlePromotionFailure开关打开,避免Full GC过于频繁。