JVM 性能调优 - 四种引用(4)

本文详细介绍了Java虚拟机中的四种引用类型:强引用、软引用、弱引用和虚引用。通过实例展示了它们在内存管理、垃圾回收以及缓存策略中的作用。强引用是最常见的引用类型,即使内存不足也不会回收;软引用在内存充足时保留,内存不足时回收,常用于缓存;弱引用比软引用更弱,只要有垃圾回收就会回收;虚引用不直接访问对象,主要用于系统通知和后续处理。理解这些引用类型有助于进行高效的JVM性能调优。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为什么会有四种引用

我们先回顾下在 Java 虚拟机内存体系(1) 中提到了的垃圾回收算法

1、引用计数法

原理:给对象添加一个引用计数器,每当有一个地方引用它,计数器的值就加一。每当有一个引用失效,计数器的值就减一。当计数器值为零时,这个对象被认为没有其他对象引用,可当作垃圾回收。

缺点:需要维护引用计数器,有一定的消耗。且较难处理循环引用的问题。(现在基本没有地方使用这种算法了,了解即可)。

2、可达性分析算法

先想象一下生活中的场景,假设张三这个人有一条狗,狗被系着一条绳子。如下图所示:

如果张三把狗遗弃了,那么这条狗和绳子就没有关联关系了,狗会被抓狗队抓起来送到宠物收容所。这里可以把张三当作 GC Roots,张三和狗之间断了联系,那么狗和绳子都会被回收。如下图所示:

可达性分析算法原理:通过一系称为 GC Roots 的对象作为起始点,从 GC Roots 的对象出发,向下搜索,如果找到的对象和 GC Roots 有直接引用或间接引用关系,则说明这个对象不是垃圾,否则,这个对象就是垃圾。

Java 中对引用的传统定义:如果 reference 类型的数据中存储的数值代表是另外一块内存的起始地址,就称 reference 数据是代表某块内存、某个对象的引用。

但是这种定义比较简单,只有被引用未被引用 两种状态。如果有些对象没什么用,但是又不想丢弃,就让它留在内存中,当内存紧张时再回收,这样有个好处,当想再用它的时候,就不用再创建一个新的出来,这个就是我们常说的将对象缓存起来。很多系统的缓存功能都符合这样的应用场景。

强引用

Cat cat = new Cat()

我们可以看到等号的右边,创建了一个对象,该对象存储在堆中,而等号的左边是这个对象的引用,存储在栈中。而这种引用关系,就被称为强引用。

当 JVM 开始回收的时候,对于强引用,即使内存不足也不会回收被强引用的对象。因此强引用是造成 Java 内存泄漏的主要原因之一。

而如果我们显示地将强引用赋值为 null(比如 cat = null),则可以认为之前的对象会被垃圾收集器回收。

编写脚本

package com.test;

public class TestStrongReference {
    public static void main(String[] args) {
        // 这样定义的默认就是强应用
        Object obj1 = new Object();

        // 使用第二个引用,指向刚刚创建的 Object 对象
        Object obj2 = obj1;

        // 将 obj1 引用设置为 null
        obj1 = null;

        // 模拟 OOM 自动 GC
        try {
            // 创建 20M 的大对象
            byte[] bytes = new byte[20 * 1024 * 1024];
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println(obj1);
            System.out.println(obj2);
        }
    }
}

运行程序

$ java -Xms5m -Xmx5m -XX:+PrintGCDetails com.test.TestStrongReference
[GC (Allocation Failure) [PSYoungGen: 918K->496K(1536K)] 918K->740K(5632K), 0.0016865 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 496K->504K(1536K)] 740K->756K(5632K), 0.0019124 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 504K->0K(1536K)] [ParOldGen: 252K->641

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

magic_kid_2010

你的支持将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值