目前大部分的JVM的GC对于新生代都采用的是复制算法,因为新生代中每次垃圾回收都要 回收大部分对象,即要复制的操作比较少,但通常并不是按照 1:1 来划分新生代。一般将新生代 划分为一块较大的 Eden 空间和两个较小的 Survivor 空间(From Space, To Space),每次使用 Eden 空间和其中的一块 Survivor 空间,当进行回收时,将该两块空间中还存活的对象复制到另 一块 Survivor 空间中。
而老年代因为每次只回收一小部分的对象,所以采用的是标记-复制算法。
对象的内存分配主要在新生代的 Eden Space 和 Survivor Space 的 From Space(Survivor 目 前存放对象的那一块),少数情况会直接分配到老生代。当新生代的 Eden Space 和 From Space 空间不足时就会发生一次 GC,进行 GC 后,Eden Space 和 From Space 区的存活对象会被挪到 To Space,然后将 Eden Space 和 From Space 进行清理。如果 To Space 无法足够存储某个对象,则将这个对象存储到老生代。 在进行 GC 后,使用的便是 Eden Space 和 To Space 了,如此反复循环。
当对象在 Survivor 区躲过一次 GC 后,其年龄就会+1。默认情况下年龄到达 15 的对象会被移到老生代中。分代收集法是目前大部分 JVM 所采用的方法,其核心思想是根据对象存活的不同生命周期将内存 划分为不同的域,一般情况下将 GC 堆划分为老生代(Tenured/Old Generation)和新生代(Young Generation)。老生代的特点是每次垃圾回收时只有少量对象需要被回收,新生代的特点是每次垃 圾回收时都有大量垃圾需要被回收,因此可以根据不同区域选择不同的算法。那什么情况下对象会从新生代进入到老年代呢?
目前大部分的JVM的GC对于新生代都采用的是复制算法,因为新生代中每次垃圾回收都要 回收大部分对象,即要复制的操作比较少,但通常并不是按照 1:1 来划分新生代。一般将新生代 划分为一块较大的 Eden 空间和两个较小的 Survivor 空间(From Space, To Space),每次使用 Eden 空间和其中的一块 Survivor 空间,当进行回收时,将该两块空间中还存活的对象复制到另 一块 Survivor 空间中。
而老年代因为每次只回收一小部分的对象,所以采用的是标记-复制算法。
对象的内存分配主要在新生代的 Eden Space 和 Survivor Space 的 From Space(Survivor 目 前存放对象的那一块),少数情况会直接分配到老生代。当新生代的 Eden Space 和 From Space 空间不足时就会发生一次 GC,进行 GC 后,Eden Space 和 From Space 区的存活对象会被挪到 To Space,然后将 Eden Space 和 From Space 进行清理。如果 To Space 无法足够存储某个对象,则将这个对象存储到老生代。 在进行 GC 后,使用的便是 Eden Space 和 To Space 了,如此反复循环。
以上是我理解的新生代和老年代的转换。
顺带提一嘴,在JDK1.8之后,将之前的“永久代”改为“元空间”了,这两者我觉得其实就是对方法区的一种实现。后者也弥补了前者的一些缺点,这里就不提了。
一周热门 更多>