关于java:Java虚拟机垃圾回收

4次阅读

共计 1742 个字符,预计需要花费 5 分钟才能阅读完成。

原文链接

回收的是什么?
答:运行程序中没有任何指针援用的对象,这个对象就是须要被回收的垃圾

垃圾回收算法

标记阶段

  • 在 GC 执行垃圾回收之前,首先须要辨别出内存中那些是存活的对象,那些是曾经死亡的对象。只有被标记为已死亡的对象,GC 才会在执行垃圾回收时,开释掉其存活所占用的内存空间。此过程被称为 垃圾标记阶段
  • 当一个对象曾经不再被任何的存活对象持续援用时,就能够宣判为曾经死亡
  • 判断对象存活的有两种形式:援用计数算法 可达性剖析算法

援用计数算法(Reference Counting)

  • 形容:对每一个对象保留一个整型的援用计数器属性,用于记录对象被援用的的状况
  • 长处:

    • 实现简略,垃圾对象便于辨识
    • 断定效率高,回收没有提早性
  • 毛病:

    • 须要独自的字段存储计数器,减少了存储空间
    • 每次赋值都须要从新更新计数器,减少了工夫开销
    • 无奈解决 循环援用

可达性剖析算法

  • 解决了 援用计数算法 中循环援用的问题,避免内存泄露
  • 可达性剖析算法是以根对象汇合(GC Roots)为起始点,依照从上至下的形式搜寻被根对象汇合所连贯的指标对象是否可达
  • 应用该算法后,内存中的存活对象都会被根汇合间接或间接的连贯着,搜寻走过的门路称为 援用链
  • 如果没有任何援用链,则不可达,阐明对象已死亡,能够标记为垃圾对象

GC Roots 蕴含以下几类元素:

  1. 虚拟机栈中援用的对象
  2. 本地办法(native 办法)中援用的对象
  3. 办法区中常量援用的对象
  4. 被同步锁 synchronized 持有的对象
  5. Java 虚拟机外部的援用

    • 根本数据类型对应的 Class 对象常驻异样对象和零碎类加载器
  6. 反映 Java 虚拟机外部状况的 JMXBean、JVMTI 中注册的回调、本地代码缓存等

finalization 机制

  • 提供对象被销毁之前的自定义解决逻辑
  • 当垃圾回收器发现没有援用指向一个对象,总会先调用这个对象的 finalize()办法
  • finalize()办法容许在子类中被重写,用于在对象被回收时进行资源开释。例如:敞开文件,断开数据库连贯

革除阶段

当胜利辨别出内存中存活对象的和死亡对象后,接下来就会执行垃圾回收,开释掉无用对象所占用的内存空间,以便有足够的空间为新对象所调配

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

执行过程:当堆中的内存空间被耗尽的时候,就会进行整个程序(stop the world),而后进行标记和革除工作。

标记:Collector 从援用根节点开始遍历,标记所有被援用的对象,并将这些对象记录在 Header 中。(找出在程序中被援用的对象,并革除其余的)

革除:Collector 从堆内存中从头到尾的进行线性遍历,如果发现某个对象在 Header 中没有标记为可达对象,则将其回收。(将不可达对象寄存在闲暇列表中,当有新对象进入时,将其地位笼罩)

毛病:

  • 效率不高
  • 在进行 GC 时,须要进行整个应用程序,导致用户体验差
  • 清理进去的闲暇内存是不间断的,产生内存碎片且须要保护一个闲暇列表

复制算法(Copying)

执行过程:当 A 空间同时存在可达和不可达对象时,将可达对象复制到 B 空间并保障空间的间断,后革除 A 空间的所以对象

长处:

  • 没有标记革除过程,实现简略
  • 将存在援用关系的对象复制过来后,保障空间的连续性,不会存在碎片

毛病:

  • 须要两倍的内存空间
  • 对于存活对象的数量远大于垃圾对象数量时,此革除算法效率差。

标记 - 压缩算法(Mark-Compact)

执行过程:

  1. 从根节点开始标记存在援用关系的对象
  2. 将这些对象压缩到内存的一端并按程序排放
  3. 革除边界外的所以对象

长处:

  • 对于“标记 - 革除算法”,因为应用了压缩性能,当有新对象分配内存时,JVM 只须要持有一个内存的起始地址即可
  • 对于“复制算法”,缩小了内存空间的占用

毛病:

  • 比照“复制算法”,效率低
  • 在挪动存在援用关系的对象时,须要调整援用的地址
  • 挪动过程中,须要全程暂停用户程序(stop the world)

分代收集算法

依据年老代和老年代的特点应用不同的内存回收算法

年老代:

针对年老代空间小,对象生命周期短,收集频繁和存活率低的特点,应用复制算法能够高效实现内存回收,复制算法使用率不高的问题,通过两个 survivor 的设计能够无效的缓解。

老年代:

老年代是空间大,对象生命周期长,存活率高和回收不频繁,应用标记 - 革除算法或标记 - 革除算法和标记 - 压缩算法联合实现内存空间的回收。

finalize

内存溢出 和内存泄露

正文完
 0