大家好,又见面了,我是你们的朋友全栈君。
Java应用程序不用程序员手动管理内存中的垃圾回收,是因为JVM有专门的垃圾回收线程做这件事。当内存不够用时,会自动触发回收。为了在效率和内存碎片之间均衡,衍生出了一系列的垃圾回收算法。
执行步骤:
缺点:
将内存划分为等大的两块,每次只使用其中的一块。当一块用完了,触发GC时,将该块中存活的对象复制到另一块区域,然后一次性清理掉这块没有用的内存。下次触发GC时将那块中存活的的又复制到这块,然后抹掉那块,循环往复。
优点
缺点:
研究发现,大多数对象都是“朝生夕死”的,即生命周期非常短。也就是说,在发生GC的时侯,其实大多数对象已经是待回收的了,还处于正常状态的对象很少。因为存活的特别少,所以在进行复制的时候,复制的对象就特别少,占用的空间也就特别小,完全不需要1:1划分内存空间。多了也是浪费,够分配就行(特殊情况不够存放再说)。 但是也有一部分对象生命周期特别长,比如缓存中的对象,还有一些别的对象等等。对于这些对象如果每次都要复制移动的话,就显的特别麻烦。另外如果某些对象特别大,如果复制的话,也放不下。因此根据对象的特点进行了分治。将整个堆划分为两大块:新生代和老年代,分别用于存放不同特点的对象。
新生代呢,存放生命周期短的对象及其体积小的对象。 老年代呢 ,存放生命周期长的 ,体积大的对象。 而且对于新生代和老年代采用了不同的垃圾回收算法。新生代使用复制算法:
将整个新生代按照8 : 1 : 1的比例划分为三块,最大的称为Eden(伊甸园)区,较小的两块分别称为To Survivor和From Survivor。
首次GC时,只需要将Eden存活的对象复制到To。然后将Eden区整体回收。再次GC时,将Eden和To存活的复制到From,循环往复这个过程。这样每次新生代中可用的内存就占整个新生代的90%,大大提高了内存利用率。
但不能保证每次存活的对象就永远少于新生代整体的10%,此时复制过去是存不下的。因此这里会用到老年代,进行分配担保,存不下的话将对象存储到老年代。若还不够,就会抛出OOM。另外如果一个对象在多次内存回收后,都还存活,也会进入老年代,这个次数通过 ‐XX:+MaxTenuringThreshold控制,最大值为15.(对象头中的4个bit存放)。
当对象的存活率比较高时,或者对象比较大时,用前面的复制算法这样复制过来,复制过去,没啥意义,且浪费时间。所以针对老年代提出了“标记整理”算法。
执行步骤:
分代收集算法其实没有什么新东西,就是上面新生代和老年代根据对象不同的特点,采用不同的算法进行回收,取名为分代收集。
对象怎样才会进入老年代呢?
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/194877.html原文链接:https://javaforall.cn