IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【Java 虚拟机原理】垃圾回收算法 ( 可达性分析算法 | GC Root 示例 | GC 回收前的两次标记 | finalize 方法示例 ) -> 正文阅读

[数据结构与算法]【Java 虚拟机原理】垃圾回收算法 ( 可达性分析算法 | GC Root 示例 | GC 回收前的两次标记 | finalize 方法示例 )





一、可达性分析算法



堆内存 中 , 存在一个 根对象 GC Root , GC Root 对象一般是如下几种情况 :

  • 线程栈 中的 栈帧 中的 局部变量表 中的 引用对象 ;
  • 方法区 中的 静态引用对象 ;
  • 方法区 中的 常量引用对象 ;
  • 本地方法栈 中的 JNI 中的 引用的对象 ;

根对象 GC Root 指向了 对象 1 ; 对象 1 又指向了 对象 2 , 对象 3 ; 对象 3 指向了 对象 4 ;

只要是 处于整个链条上的对象 , 都是 非垃圾对象 , 不能进行回收的对象 ;

不处于 引用链条 上的对象 , 就是 垃圾对象 ;


下图中 , 紫色的是存活对象 , 白色的是可回收的 垃圾对象 ;

在这里插入图片描述





二、GC Root 示例



找出下面程序中的 GC Root 对象 ;

public class HelloWorld {

    public static HelloWorld mHelloWorld = new HelloWorld();

    public int add() {
        int a = 1;
        int b = 1;
        int c = a + b;
        return c;
    }

    public static void main(String[] args) {
        HelloWorld helloWorld = new HelloWorld();
        helloWorld.add();
    }
}

在这里插入图片描述

13 13 13 行的 helloWorld 对象是 GC Root 对象 , 符合 " 线程栈 中的 栈帧 中的 局部变量表 中的 引用对象 " 条件 ;

helloWorld 对象中有其它引用对象 , 只要引用链条没有断 , 那么链条上的对象都是 非垃圾对象 ;

一旦执行了 helloWorld = null; 语句 , 那么该对象及以下的对象就没有了引用链条 , 这个对象及之下的对象就都变成了 垃圾对象 ;





三、GC 回收前的两次标记



当对象被 定义为垃圾对象后 , 并不会马上被回收 , 只是判了个死缓 , 没有真正执行垃圾回收 ;

当 GC Root 引用链断开后 , 对象不可达 ;

JVM 会对这些 不可达对象 进行一次标记 , 然后执行一次筛选 , 执行该对象的 finalize 方法 ,

public class HelloWorld {
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
    }
}

finalize 方法是对象被 GC 垃圾回收之前 , 被调用的方法 , 该方法不能保证一定能执行完毕 , JVM 会给对象一个时间限制 , 在这个时间内执行 finalize 方法 , 重写的该方法中不要执行很耗时的操作 ;

在对象的 finalize 方法中 , 如果不想被回收 , 可以再次添加一个引用链 , 让 GC Root 对象引用自己 ;


之后 JVM 会对不可达对象 进行第二次标记 , 此时如果发现 该对象 仍然是垃圾对象 , 此时直接将该对象回收 ;

finalize 方法只会被调用一次 , JVM 对 对象第二次标记时 , 发现对象如果没有被引用 , 直接回收 , 不再调用 finalize 方法 ;





四、finalize 方法示例



创建一个对象 , 赋值给变量 A , 然后将 A 置空 , 该对象就变成了垃圾对象 ;

在 finalize 方法中 , 对象尝试自救 , 将自己赋值给 A , 这样该对象又变成了 非垃圾对象 ;

调用 System.gc() 方法后 , 一般需要暂停几秒 , 等待 finalize 方法调用 ;


这里将 A 两次置空 , 第一次调用了 finalize 方法 , 自救成功 , 没有被回收 ;

第二次置空后 , finalize 方法不再调用 , 被回收了 ;


代码示例 :

public class HelloWorld {

    public static HelloWorld A;

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("finalize 被调用");
        A = this;
    }

    public static void main(String[] args) throws InterruptedException {
        A = new HelloWorld();

        // 将 对象 变为垃圾对象
        A = null;

        // 进行垃圾回收
        System.gc();
        // 由于 gc 的优先级比较低
        //      等待 1000ms 看 finalize 是否被调用
        Thread.sleep(1000);

        // 本次 GC 调用之前
        //      先调用了 finalize 方法
        //      为对象添加了 GC Root 引用链
        //      该方法只会调用一次
        if (A == null) {
            System.out.println("对象被回收");
        } else {
            System.out.println("对象未被回收");
        }

        // 将 对象 变为垃圾对象
        A = null;

        // 进行垃圾回收
        System.gc();
        // 由于 gc 的优先级比较低
        //      等待 1000ms 看 finalize 是否被调用
        Thread.sleep(1000);

        // 本次调用 GC
        //      直接判断对象是否有引用链
        //      不再调用 finalize 方法
        //      发现没有引用链 , 直接回收
        if (A == null) {
            System.out.println("对象被回收");
        } else {
            System.out.println("对象未被回收");
        }
    }
}

执行结果 :

finalize 被调用
对象未被回收
对象被回收
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-09-04 17:47:48  更:2021-09-04 17:48:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 1:43:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码