目录
1.内存分配和回收策略
堆空间的基本结构:
- Java 堆还可以细分为:新生代和老年代
- 再细致一点有:Eden 空间、From Survivor、To Survivor 空间等。进一步划分的目的是更好地回收内存,或者更快地分配内存
- 上图所示的 eden 区、s0("From") 区、s1("To") 区都属于新生代,tentired 区属于老年代。
(1)优先分配到Eden
- 大部分情况,对象都会首先在 Eden 区域分配,
- 在Eden中没有足够的空间分配的时候,会发生一次MiniorGC
以下对两种GC先做解释:
JVM在进行GC时,并非每次都对上面三个内存区域一起回收的,大部分时候回收的都是指新生代,因此GC按照回收的区域又分为两种类型:
- 普通GC(Minor GC):只针对新生代区域的GC,因为Java对象大多都具备朝生夕灭的特性,所以MiniorGC非常频繁,一般回收速度也比较快
- 全局GC(Major GC or Full GC):针对老年代的GC,偶尔伴随对新生代的minor GC以及方法区的GC,Major GC的速度一般会比Minor GC慢10倍以上
MinorGC的过程(复制->清空->互换):
- 1.eden、SurvivorFrom复制到SurvivorTo,年龄+1
- 首先,当Eden区满的时候会触发第一次Minor GC,把还活着的对象拷贝到SurrvivorFrom区,
- 当Eden区再次触发GC的时候会扫描Eden区和From区域,对这两个区域进行垃圾回收,经过这次回收后还存活的对象,则直接复制到To区域(如果对象的年龄已经达到了老年的标准,则复制到老年代区),同时把Eden过来的对象和From区域过来的对象的年龄分别+1(如果这是第二次Minor GC的话,那Eden过来的对象的年龄变成了1,From区域过来的对象的年龄变成2,From区域的对象是上一次MinorGC从Eden中过来的,当时对象年龄+1)
- 2.清空eden、SurvivorFrom
- 然后清空Eden和SurvivorFrom中的对象,这个时候,"From"和"To"会交换他们的角色,也就是新的"To"就是上次GC前的“From”,,直到“To”区被填满,"To"区被填满之后,会将所有对象移动到年老代中,
- 3.SurvivorTo和SurvivorFrom互换
- ·最后,SurvivorTo和SurvivorFrom互换,原SurvivorTo成为下一次GC时的SurvivorFrom区。新的"From"就是上次GC前的"To"。不管怎样,都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程,部分对象会在From和To区域中复制来复制去,直到“To”区域被填满,或分代年龄达到设定值(由JVM参数MaxTenuring Threshold决定这个参数默认是15,而分代年龄的保存是在对象头当中),最终如果还是存活,就存入到老年代,总结起来就是:复制之后有交换,谁空谁是to
注意:
- 1.当JVM无法为一个新的对象分配空间时会触发Minor GC