java 8的内存分代改进_Java内存分代、垃圾回收

内存分代

一个应用启动,操作系统会给他分配一个初始的内存大小,由上可知,这部分内存大部分应该属于堆内存,JVM 为了更好地利用管理这部分内存,对该区域做了划分。一部分成为新生代,另一部分称为老年代。

一开始对象的创建都发生在新生代,随着对象的不断创建,如果新生代没有空间创建新对象,将会发生 GC ,这时的 GC 称之为 Minor GC,位于新生代的对象每经过一次 Minor GC 后,如果这个对象没有被回收,则为自己的标记数加1,这个标记数用于标识这个对象经历了多少次的 Minor GC,对于 Sun 的 Hotspot 虚拟机,如果这个次数超过 15 ,该对象才会被移动到老年代。

随着时间的推移,如果老年代也没有足够的空间容纳对象,老年代也会试着发起 GC,这时的 GC 被称为 Full GC。

相比 Minor GC,Full GC 发生的次数比较少,但是每发生一次 Full GC,整个堆内存区域都需要执行一次垃圾回收,这对程序性能造成的影响比 Minor GC 大很多。所以我们应该尽量避免或者减少 Full GC 的发生。

同时,在堆内存区域,发生最多的 GC 情形就是新生代的 Minor GC 了,因为所有的对象会优先去新生代开辟空间,所以这块的内存变化会很快,只有内存不够用,就会发生 GC,但是一般的 Minor GC 执行比 Full GC 快很多。为什么呢?因为新生代和老年代的垃圾回收算法不一样。

垃圾回收算法

标记-清除算法(Mark-Sweep)

这是最基础的收集算法,如它的名字一样,算法分为“标记”和“清除”两个阶段:

首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。

之所以说它是最基础的收集算法,是因为后续的收集算法都是基于这种思路并对其缺点进行改进而得到的。

它的主要缺点有两个:一个是效率问题,标记和清除过程的效率都不高;另外一个是空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致,当程序在以后的运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。

复制算法(Copying)

为了解决效率问题,一种称为“复制”(Copying)的收集算法出现了,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。

这样使得每次都是对其中的一块进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。只是这种算法的代价是将内存缩小为原来的一半,未免太高了一点。

但是这种算法的效率相当高,所以,现在的商业虚拟机都采用这种收集算法来回收新生代。为什么新生代可以使用复制算法呢?

IBM 有专门研究表明,新生代中的对象 98% 都是朝生夕死,所以就不需要按照1:1的比例来划分内存空间。这里鉴于此,新生代采用了如下的划分策略。

现在把新生代再划分为三部分,一块较大的 Eden(伊甸园) 和两块较小的 Survivor(幸存者) 区域。

当回收时,将 Eden 和 Survivor 中还存活着的对象一次性地拷贝到另外一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor的空间。HotSpot 虚拟机默认Eden和Survivor的大小比例是8∶1,也就是每次新生代中可用内存空间为整个新生代容量的90%(80%+10%),只有10%的内存是会被“浪费”的。

这样清理完成后,原来的 Survivor 就空了,并一直保持为空,直到下次 Minor GC 时,它再作为存活对象的盛放地。两个 Survivor 就这样轮流当做 GC 过程中新生代存活对象的中转站。

但是,如果使用复制算法的内存区域有大量的存活对象时,复制算法就会变得捉襟见肘,这时需要更大的 Survivor 区用于盛放那些存活对象,甚至可能需要 1:1的比例。所以针对堆内存区域的老年代,就有了下面的算法。

标记-整理算法

标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。这种方法避免了碎片的产生,同时也不需要一块额外的内存空间,对于老年代会比较合适。

但是相比复制算法,虽然该算法占用的内存空间少,但是耗费的垃圾回收时间会比复制算法久,所以上面也说了

我们应该尽量避免或者减少 Full GC 的发生。

这两种算法用精炼的语言描述就是

复制算法:用空间换时间

标记-整理算法:用时间换空间

一句话 鱼与熊掌不可兼得,但是针对新生代和老年代,他们都是最佳的选择。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值