在JVM中 判定哪些对象是垃圾?

news2024/9/23 13:21:02

目录

垃圾的条件

1、引用计数法

2、可达性分析

3、强引用

4、软引用

5、弱引用

6、虚引用


判断垃圾的条件

在Java虚拟机(JVM)中,垃圾收集器负责管理内存,其中的垃圾收集算法用于确定哪些对象是垃圾,可以被回收以释放内存空间。Java中主要使用的是自动内存管理,垃圾收集器会自动识别和回收不再被程序引用的对象。以下是一些判定对象为垃圾的条件:

1、引用计数法

引用计数法是一种简单而直观的垃圾收集算法,其核心思想是通过在对象头中添加一个引用计数器,记录该对象被引用的次数。每当有一个新的引用指向该对象时,引用计数加一;当引用被删除或者超出作用范围时,引用计数减一。当引用计数为零时,表示该对象不再被引用,即可以被回收。

然而,引用计数法有一个明显的缺陷,即难以处理循环引用的情况。例如,两个对象互相引用,它们的引用计数永远不会变为零,即使它们已经不再被程序所使用。

以下是一个简单的引用计数法的Java代码示例:

class ReferenceCountingObject {
    private int referenceCount = 0;

    public ReferenceCountingObject() {
        // 对象初始化时,引用计数为 0
    }

    public void addReference() {
        referenceCount++;
    }

    public void removeReference() {
        referenceCount--;
        if (referenceCount == 0) {
            // 当引用计数为零时,可以进行垃圾回收操作
            System.out.println("对象被回收");
        }
    }
}

public class ReferenceCountingExample {
    public static void main(String[] args) {
        // 创建两个对象
        ReferenceCountingObject obj1 = new ReferenceCountingObject();
        ReferenceCountingObject obj2 = new ReferenceCountingObject();

        // obj1 引用计数加一
        obj1.addReference();
        // obj2 引用计数加一
        obj2.addReference();

        // obj1 引用计数减一
        obj1.removeReference();

        // obj1 引用计数为零,可以进行垃圾回收
        // obj2 引用计数仍为一
    }
}

2、可达性分析

可达性分析是Java虚拟机中垃圾收集的核心算法之一,它主要通过判断对象是否能够从一组称为"GC Roots"的根对象出发,通过引用链追踪,最终判断对象是否可达。以下是关于可达性分析的一些详细细节和Java代码示例:

  1. GC Roots: GC Roots包括虚拟机栈中引用的对象、方法区中类静态属性引用的对象、方法区中常量引用的对象以及本地方法栈中JNI(Java Native Interface)引用的对象。这些对象被认为是程序的根对象,是可达性分析的起始点。

  2. 可达性分析过程: 从GC Roots出发,通过对象引用链逐步追踪,判断对象是否能够被程序访问到。如果对象能够通过一系列引用到达GC Roots,则该对象被认为是可达的;反之,如果无法到达,则被认为是不可达的。

  3. 标记-清除算法: 在可达性分析过程中,标记-清除算法是一种常用的垃圾收集算法。通过标记可达的对象,然后清除不可达的对象,最终回收被标记的垃圾。

下面是一个简单的Java代码示例,演示了可达性分析的基本原理:

class MyClass {
    // 成员变量,作为引用
    private MyClass reference;

    public MyClass() {
        this.reference = null;
    }

    public void setReference(MyClass anotherObject) {
        this.reference = anotherObject;
    }
}

public class ReachabilityAnalysisExample {
    public static void main(String[] args) {
        // 创建对象1
        MyClass obj1 = new MyClass();
        // 创建对象2
        MyClass obj2 = new MyClass();

        // obj1 的 reference 成员变量指向 obj2
        obj1.setReference(obj2);

        // obj2 的 reference 成员变量为空,不指向其他对象

        // 现在,obj1 和 obj2 都是可达的,因为它们可以通过引用链相互访问

        // 将 obj1 置为 null,切断对 obj1 的引用
        obj1 = null;

        // 现在,obj1 不可达,因为没有其他引用指向它,但 obj2 仍然可达

        // 执行垃圾回收
        System.gc();

        // 垃圾回收器可能会回收不可达的对象,释放其占用的内存

        // 在实际应用中,Java 虚拟机会根据不同的垃圾收集算法和策略执行垃圾回收
    }
}

 

3、强引用

强引用是最常见的引用类型,只要强引用存在,垃圾收集器就不会回收被引用的对象。当没有任何强引用指向一个对象时,该对象就变得不可达。

  • 特点: 强引用是最常见的引用类型,它会使对象始终保持存活。只要存在强引用指向一个对象,垃圾收集器就不会回收该对象。

  • 使用场景: 大多数对象的引用都是强引用,例如通过 new 操作符创建的对象就是强引用。当程序员希望确保对象不被垃圾收集器回收时,使用强引用是合适的。

Object obj = new Object(); // 强引用

 

4、软引用

软引用用于描述一些还有用但非必需的对象。在系统将要发生内存溢出之前,会尝试回收软引用指向的对象。

  • 特点: 软引用用于描述一些还有用但非必需的对象。当系统内存不足时,垃圾收集器会根据软引用的情况来决定是否回收该对象,以释放内存。

  • 使用场景: 软引用通常用于实现缓存策略,允许在内存不足时回收部分缓存而不会导致程序崩溃。

SoftReference<Object> softRef = new SoftReference<>(new Object());
Object obj = softRef.get(); // 获取软引用指向的对象

5、弱引用

弱引用也用于描述非必需对象,但它的生命周期比软引用更短。当垃圾收集器运行时,无论内存是否足够,都会回收被弱引用指向的对象。

  • 特点: 弱引用描述的是非必需对象,其生命周期比软引用更短。当垃圾收集器运行时,无论内存是否足够,都会回收被弱引用指向的对象。

  • 使用场景: 弱引用常用于实现对象缓存,但不希望缓存的对象影响垃圾回收。

WeakReference<Object> weakRef = new WeakReference<>(new Object());
Object obj = weakRef.get(); // 获取弱引用指向的对象

6、虚引用

虚引用是最弱的引用类型,几乎没有保持对象存活的作用。主要用于对象被回收前的一些清理操作。

  • 特点: 虚引用是最弱的引用类型,几乎没有保持对象存活的作用。主要用于对象被回收前的一些清理操作。虚引用必须和引用队列(ReferenceQueue)一起使用。

  • 使用场景: 虚引用主要用于跟踪对象被垃圾收集的状态,执行一些清理操作或者资源释放。

ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), referenceQueue);
// 虚引用不提供 get 方法,因为其并不保持对象的存活,需要通过 ReferenceQueue 来获取通知
Object obj = phantomRef.get(); // 返回始终为 null

 总体而言,这些引用类型在Java中提供了更灵活的内存管理手段,允许开发人员根据不同的场景来控制对象的生命周期。选择合适的引用类型取决于应用程序的需求,以及对内存使用和性能的权衡。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1248900.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

0002Java程序设计-springboot在线考试系统小程序

文章目录 **摘 要****目录**系统实现开发环境 编程技术交流、源码分享、模板分享、网课分享 企鹅&#x1f427;裙&#xff1a;776871563 摘 要 本毕业设计的内容是设计并且实现一个基于springboot的在线考试系统小程序。它是在Windows下&#xff0c;以MYSQL为数据库开发平台&…

记一次linux操作系统实验

前言 最近完成了一个需要修改和编译linux内核源码的操作系统实验&#xff0c;个人感觉这个实验还是比较有意思的。这次实验总共耗时4天&#xff0c;从对linux实现零基础&#xff0c;通过查阅资料和不断尝试&#xff0c;直到完成实验目标&#xff0c;在这过程中确实也收获颇丰&…

井盖位移监测系统怎么监测井盖位移

党的二十大报告提出&#xff0c;坚持人民城市人民建、人民城市为人民&#xff0c;提高城市规划、建设、治理水平。秉持依法治理、创新引领的理念&#xff0c;市政府应该坚定推进窨井盖安全管理工作&#xff0c;不断加大排查整治力度&#xff0c;弥补设施安全管理短板&#xff0…

每日一练:“打家劫舍“(House Robber)问题 II

有想要了解打家劫舍初级问题的&#xff0c;可以点击下面链接查看&#xff01; 每日一练&#xff1a;“打家劫舍“&#xff08;House Robber&#xff09;问题 I 1. 问题 假设有房屋形成一个环形&#xff0c;即第一个房屋和最后一个房屋也相邻&#xff0c;每个房屋里都存放着一定…

Java数组的复制、截取(内含例题:力扣-189.轮转数组)

目录 数组的复制、截取&#xff1a; 1、使用Arrays中的copyOf方法完成数组的拷贝 2、使用Arrays中的copyofRange方法完成数组的拷贝 题目链接&#xff1a; 数组的复制、截取&#xff1a; 1、使用Arrays中的copyOf方法完成数组的拷贝 public class Csdn {public static vo…

【Git】一文教你学会 submodule 的增、查、改、删

添加子模块 $ git submodule add <url> <path>url 为想要添加的子模块路径path 为子模块存放的本地路径 示例&#xff0c;添加 r-tinymaix 为子模块到主仓库 ./sdk/packages/online-packages/r-tinymaix 路径下&#xff0c;命令如下所示&#xff1a; $ git subm…

UI自动化测试神器:RunnerGo测试平台

可以直接进入官网下载开源版或点击右上角体验企业版体验 RunnerGo UI自动化平台 RunnerGo提供从API管理到API性能再到可视化的API自动化、UI自动化测试功能模块&#xff0c;覆盖了整个产品测试周期。 RunnerGo UI自动化基于Selenium浏览器自动化方案构建&#xff0c;内嵌高度…

可持续创新 精选路线

在加速企业数字化转型、 实现智能制造的升级之路上&#xff01; 使用好的工具固然重要&#xff0c; 而有好工具&#xff0c;也要会用工具。生信科技不仅为企业提供强大的产品支持&#xff0c; 更有全方位的定制化服务&#xff0c; 提升工程师的工具应用能力&#xff0c; 让企业…

海外https代理ip如何保障信息安全?该怎么选择?

海外https代理ip是指通信协议为https的海外真实网络地址ip&#xff0c;通常应用在各种跨境业务中。 一、什么是HTTPS协议 HTTP协议是一个应用层协议&#xff0c;通常运行在TCP协议之上。它是一个明文协议&#xff0c;客户端发起请求&#xff0c;服务端给出响应的响应。由于网…

pat实现基于邻接表表示的深度优先遍历[含非递归写法]

文章目录 1.递归2.非递归 1.递归 void DFS(ALGraph G, int v) {visited[v] 1;printf("%c ", G.vertices[v].data);for (ArcNode* cur G.vertices[v].firstarc; cur ! nullptr; cur cur->nextarc){if (!visited[cur->adjvex])DFS(G, cur->adjvex);} }2.非…

matlab画双坐标图的样式

matlab画双坐标图的样式 %% clc,clear,close all; t0:0.1:9*pi; figure; [AX,Ha,Hb]plotyy(t,sin(t),t,exp(t)); % 绘图并创建句柄 % ----------------- 设置刻度 set(AX(1),yTick,[-1.250:0.25:1.25]) % 设置左边Y轴的刻度 set(AX(2),yTick,[0:50:350]) …

2023年【危险化学品经营单位安全管理人员】考试内容及危险化学品经营单位安全管理人员最新解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 危险化学品经营单位安全管理人员考试内容是安全生产模拟考试一点通生成的&#xff0c;危险化学品经营单位安全管理人员证模拟考试题库是根据危险化学品经营单位安全管理人员最新版教材汇编出危险化学品经营单位安全管…

HarmonyOS开发:ArkTs常见数据类型

前言 无论是Android还是iOS开发&#xff0c;都提供了多种数据类型用于常见的业务开发&#xff0c;但在ArkTs中&#xff0c;数据类型就大有不同&#xff0c;比如int&#xff0c;float&#xff0c;double&#xff0c;long统一就是number类型&#xff0c;当然了也不存在char类型&…

新式的拉式膜片弹簧离合器设计机械设计CAD

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;离合器 获取完整论文报告工程源文件 减震弹簧 摩擦片 膜片弹簧 压盘 轴 扭转减震器 从动盘 离合器 离合器的结构设计 为了达到计划书所给的数据要求&#xff0c;设计时应根据车型的类别、使用要求、制造条件&#xff0c;…

Flink-简介与基础

Flink-简介与基础 一、Flink起源二、Flink数据处理模式1.批处理2.流处理3.Flink流批一体处理 三、Flink架构1.Flink集群2.Flink Program3.JobManager4.TaskManager 四、Flink应用程序五、Flink高级特性1.时间流&#xff08;Time&#xff09;和窗口&#xff08;Window&#xff0…

FreeRTOS深入教程(信号量源码分析)

文章目录 前言一.创建信号量二.释放信号量三.获取信号量成功获取获取不成功 总结 前言 本篇文章将为大家讲解信号量&#xff0c;源码分析。 在 FreeRTOS 中&#xff0c;信号量的实现基于队列。这种设计的思想是利用队列的特性来实现信号量&#xff0c;因为信号量可以被视为只…

借助 XEOS V6, 农牧龙头企业实现原有存储的高效在线替换

面对旧有存储系统的应用不足&#xff0c;某大型现代农牧龙头企业采用了星辰天合的对象存储 XEOS V6 方案&#xff0c; 该方案以其卓越的技术架构和同城双活异地灾备的解决方案完整性&#xff0c;在无缝高效完成系统替换的同时&#xff0c;可以极大地提升系统的灵活性和业务的连…

C/C++ 实现Socket交互式服务端

在 Windows 操作系统中&#xff0c;原生提供了强大的网络编程支持&#xff0c;允许开发者使用 Socket API 进行网络通信&#xff0c;通过 Socket API&#xff0c;开发者可以创建、连接、发送和接收数据&#xff0c;实现网络通信。本文将深入探讨如何通过调用原生网络 API 实现同…

RabbitMQ之发送者(生产者)可靠性

文章目录 前言一、生产者重试机制二、生产者确认机制实现生产者确认&#xff08;1&#xff09;定义ReturnCallback&#xff08;2&#xff09;定义ConfirmCallback 总结 前言 生产者重试机制、生产者确认机制。 一、生产者重试机制 问题&#xff1a;生产者发送消息时&#xff0…

【python VS vba】(6) python的常用函数print()的各种用法和细节(未完成)

1 基本语法 print() 3.0 都是函数用法 2 可打印的各种对象 直接打印对象 直接打印数组 直接打印string 数值等 3 打印的各种内容如何连接 逗号分隔 &不行 3 转义符 可用转义符 换行的特殊符号 /n 4 print() 里带变量怎么输出 试验了4种输出带变量的方法&#xf…