深入JVM工作原理(二)
(接着JVM工作原理(一),继续更新JVM的内容)
一、详解 新生代和老年代
(一)新生代
- java堆可以分为新生代和老年代,默认创建的对象都是先放在新生代,当gc收集发生之后,若该对象没有没回收,并且达到了老年代的年龄,就被转移到老年代。
- 一般占据堆的1/3空间。由于频繁创建对象,所以新生代会频繁触发MinorGC进行垃圾回收。
新生代又分为 Eden区、SurvivorFrom、ServivorTo三个区。 -
Eden区: Java新对象的出生地,当Eden区内存不够的时候就会触发MinorGC,对新生代区进行一次垃圾回收。
SurvivorTo:保留了一次MinorGC过程中的幸存者。
SurvivorFrom:上一次GC的幸存者,作为这一次GC的被扫描者。 -
MinorGC的过程:MinorGC采用复制算法。首先,把Eden和SurvivorFrom区域中存活的对象复制到SurvicorTo区域然后,清空Eden和SurvicorFrom中的对象;最后,SurvicorTo和SurvicorFrom互换,原SurvicorTo成为下一次GC时的SurvicorFrom区。
注意:IBM研究发现新生代对象98%都是“朝生夕灭”的,所以Eden和两块Survivor三块区域内存比例为:8:1:1,采用复制算法90%的内存我们是可用的!
(二)老年代
-
大对象直接进入老年代
什么是大对象?
回答:所谓大对象就是指,需要连续的大量内存的对象,最典型的就是:很长的字符串及数组。所以大对象对虚拟机内存的分配是一个坏消息,还有更坏的消息就是:java虚拟机遇到一群“朝生夕灭”的“短命大对象”,因为经常出现大对象容易导致内存还有不少空间就提前触发垃圾回收以获取足够的空间来“安置”它们。 -
长期存活的对象进入老年代
有人会问多久算长期?
回答:虚拟机给每个对象都有年龄:age 一个的计数器;假设对象在Eden出生并进行第一次Minor GC后仍存活,并且能被Survicor容纳,对象进入到Survicor区域,将对行年龄设为:1。对象在Survicor区域每熬过一次Minor GC,年龄就+1,当年龄增加到一定程度(默认15岁),就会进入老年代。 -
动态对象年龄判断
为了更好的适应不同的内存情况,并不是非要上面说的,当对象达到一定年龄才可以进入老年代。
现要求:如果Survicor空间中相同年龄所有对象大小的总和大于等于Survicor空间的一半,年龄大于或者等于该年龄的对象直接进入老年代。 -
Minor GC 和Full GC 有什么不一样
Minor GC :发生在新生代的垃圾回收动作,因为java对象大多都“朝生夕灭”,所以Minor GC操作很频繁,一般回收速度也快。
Full GC:发生在老年代的GC,经常会伴随至少一次的Minor GC,Full GC速度会比Minor GC慢10倍以上。
(后续还会更新)