zoukankan      html  css  js  c++  java
  • 判断Java对象存活的算法、垃圾回收算法

    判断Java对象存活的算法

    一、引用计数算法

    给对象添加一个引用计数器,每当一个地方引用它的时候就将计数器加1,当引用失效的时候就将计数器减1,任何时刻计数器为0的对象都不可再被使用。这种算法虽然简单,但是有个致命的缺点,就是不能适用于相互引用的情况。

    二、可达性分析算法

    通过一系列称为"GC Roots"的对象作为起始点,从这些节点往下搜索,搜索走过的路径称为引用链(Reference Chain)。当一个对象不在任何引用链上的时候,就表示这个对象不可达,不可用了。

    可作为GC Roots的对象包括:

    1、虚拟机栈中引用的对象

    2、Native方法栈中引用的对象

    3、方法区中静态变量和常量引用的对象

    一、标记清除算法

    标记清除(mark-sweep)算法是现代垃圾回收算法的思想基础。标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。先标记,再清除。

    有2个缺点:

    1、效率问题。标记和清除两个过程的效率都不高。

    2、空间问题。标记清除后会产生大量不连续的内存碎片,碎片太多可能会导致以后在程序运行过程中需要分配较大的对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集操作。

    二、标记整理算法

    标记整理算法和标记清除算法类似,不同的是,标记整理算法在标记完对象后,不是直接对可回收对象进行清除,而是先让所有存活的对象都往一端移动,然后再清除掉边界以外的内存。

    相对于标记清除算法,标记整理算法解决了内存碎片的问题,但效率不高的问题依然存在。

    三、复制算法

    复制算法可以解决效率问题。它将可用内存分成大小相等的两块,每次只使用其中的一块,当这一块用完了,就将还存活着的对象复制到另一块上面,然后再把原来半块的对象全部清理掉。这样,每次都是对整个半区进行内存回收,内存分配时也不用考虑内存碎片的情况,按顺序分配即可。

    复制算法的优点是效率高,没有内存碎片。但也有2个缺点:

    1、浪费一半的内存空间。

    2、在对象存活率较高的情况下,会有较多的复制操作,效率会变低。

    四、分代收集算法

    根据对象存活周期的不同,将内存分为几块,一般是把Java堆分为新生代和老年代,然后根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集都有大批对象死去,只有少量存活,就选用复制算法。而老年代对象存活率高,必须采用标记清除算法或者标记整理算法来回收内存。

    新生代又可细分为一块较大的Eden空间和两块较小的Survivor空间(HotSpot虚拟机默认Eden和Survivor的大小比例是8:1,即Eden空间占堆内存的80%,两个Survivor空间各占10%),每次只使用Eden空间和一块Survivor空间。对象优先在Eden空间分配内存,如果对象过大,则会分配到老年代空间。新生代回收时,会把Eden空间和Survivor空间中存活的对象复制到另一块Survivor空间,然后清理掉Eden空间和之前Survivor空间的对象。当然,如果在复制的时候,新的Survivor空间不够,则会把多出来的对象复制到老年代空间。同时,新生代中存活时间较长的对象也会进入老年代。

  • 相关阅读:
    并发编程 之 生产者消费者模型
    并发编程 之 IPC机制
    Django + DRF + Elasticsearch 实现搜索功能
    时间上相邻query,前缀去重
    列表套字典,将字典元素去重
    K8s
    docker
    数据处理
    Django日志配配置
    Canvas 获取颜色值
  • 原文地址:https://www.cnblogs.com/koushr/p/11067161.html
Copyright © 2011-2022 走看看