zoukankan      html  css  js  c++  java
  • JVM——对象已“死”的判定

    主要针对Java堆和方法区

    1、判断对象是否已“死”

    Java堆中存放着几乎所有的对象实例,垃圾回收器在对堆进行回收之前,首先应该判断这些对象哪些还“存活”,哪些已经“死亡”。

    (1)引用计数法

    A. 工作流程

         给每个对象附加一个计数器,每当有一个地方引用此对象。计数器+1;每当有一个地方不再引用此对象,计数器-1;在任意时刻,只要对象引用计数器值为0,任务此对象已经“死亡”。(没有“死亡”的对象一定不会被垃圾回收回收)

    System.gc()”:强制进行垃圾回

    B. 优缺点

    优点:实现简单,判定效率较高,大多数情况下都是一个不错的算法(phthonC++智能指针都采用引用计数器算法判断无用对象)

    缺点:无法处理对象循环引用问题,所以Java不采用引用计数算法。

    (2)可达性分析算法

    A. 工作流程

    通过一系列称之为GC Roots”的对象作为起点,然后向下搜索,如果当前对象到GC Roots有路可走(GC Roots到当前对象可达),认为此对象还存活;如果当前对象到GC Roots没有引用链,认为此对象不可用。

    B. 什么对象可作GC Roots

    1)虚拟机栈中(局部变量表)引用的对象

    2)本地方法栈中引用的对象

    3)方法区中类静态变量引用的对象

    4)方法区中常量引用的对象

    (3)再谈引用

    jdk1.2对引用进行了扩充:

    A. 强引用(Strong Reference

    强引用指的是程序代码中普遍存在的,类似于Object obj = new Object()这类引用,只要当前对象至少有一个强引用存在,垃圾回收器就永远不会回收此对象实例,即便发生OutOfMemoryError异常也不会。

    B. 软引用(Soft Reference

    软引用描述的是一些有用但不必须的对象,对于只被软引用引用的对象,在内存足够时,不会进行GC,在系统即将发生OutOfMemoryError异常之前,会将这些对象列入回收范围进行第二次GC,如果这次回收还没有足够空间,JVM会抛出OutOfMemoryError异常信息。

        Jdk1.2之后,用SoftReference类来描述软引用。

    C. 弱引用(Weak Reference

    弱引用描述的是非必须对象,但它的强度弱于软引用。仅仅被弱引用引用的对象,最多只能生存到下一次GC之前,当垃圾回收器开始工作时,不管当前内存是否够用,都会回收掉被弱引用引用的对象。

    Jdk1.2之后,用WeakReference类来描述弱引用

    D. 虚引用(Phantom Reference

    虚引用也被称为“幽灵引用”或“幻影引用”。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用的目的:在这个对象被垃圾回收时会收到一个系统通知。

    Jdk1.2之后,PhantomReference类来实现虚引用。

    (4)判断一个对象真正的“死亡”

    判断一个对象真正“死亡”需要经历两次标记。如果当前对象在进行可达性分析之后,发现它到GC Roots不可达,则会对其进行第一次标记并且进行一次筛选。帅选的依据有两点:

    1)如果当前对象没有覆写finalize()方法或者它的finalize()方法已经被JVM调用过,则认为此对象真正“死亡”,下一次GC时将其回收。

    2)如果当前对象通过帅选,那么对象会被放置在一个F-Queue的队列中,并在稍后有JVMFianlizer线程执行它的finalize()方法。

    Finalize()方法时对象逃脱死亡经历的最后一次机会,垃圾回收器将对F-Queue队列进行第二次标记,如果对象在finalize()成功解救自己,则会被移出回收序列,否则,宣告死亡。

    finalize()方法只会被JVM调用一次,不推荐使用,在jdk1.9之后,finalize()方法加上了@Deprecated(过期处理)注解。

    (5)回收方法区

    方法区的垃圾回收主要回收两部分内容:废弃常量、无用类

    1)废弃常量:废弃常量的回收与Java堆对象回收类似。

    2)无用类:

    判断一个类为无用类条件有三个:

    a. 该类的所有实例对象都已经被垃圾回收,即在Java堆中不存在任何该类实例。

    b. 加载该类的ClassLoad也已经被回收。

    c. 该类对应的Class对象没有在任何其他地方被引用,即无法通过反射访问该类的属性、方法。

    JVM会对满足以上三点的无用类进行回收(类卸载),仅仅是“可能”。

    大量使用反射,动态代理的场景下,JVM会不定期的对方法区进行回收来防止永久代溢出。

  • 相关阅读:
    Python3之random模块常用方法
    Go语言学习笔记(九)之数组
    Go语言学习笔记之简单的几个排序
    Go语言学习笔记(八)
    Python3之logging模块
    Go语言学习笔记(六)
    123. Best Time to Buy and Sell Stock III(js)
    122. Best Time to Buy and Sell Stock II(js)
    121. Best Time to Buy and Sell Stock(js)
    120. Triangle(js)
  • 原文地址:https://www.cnblogs.com/edda/p/12601223.html
Copyright © 2011-2022 走看看