当前位置: 首页 > article >正文

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

为什么会有四种引用

我们先回顾下在 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 F


http://www.kler.cn/a/229524.html

相关文章:

  • fastadmin插件wanlshop使用方法
  • GitLab本地服务器配置ssh和克隆项目
  • IOS界面传值-OC
  • 开源项目stable-diffusion-webui部署及生成照片
  • 14X505-1《火灾自动报警系统设计规范图示》中相关数据和总线制的个人理解
  • Bash语言的多线程编程
  • 【动态规划】【图论】【C++算法】1928规定时间内到达终点的最小花费
  • 如何在Linux中安装新版的Python软件
  • Linux死机排查方法——内存日志
  • synchronized内部工作原理
  • OpenFeign之@Headers注解
  • PYthon进阶--网页采集器(基于百度搜索的Python3爬虫程序)
  • 【防止重复提交】Redis + AOP + 注解的方式实现分布式锁
  • Nim游戏
  • 使用 IDEA 开发一个简单易用的 SDK
  • DevOps落地笔记-15|混沌工程:通过问题注入提高系统可靠性
  • re:从0开始的CSS学习之路 1. CSS语法规则
  • 数论:修改数列
  • Spring Data Envers 数据审计实战
  • 编码安全风险是什么,如何进行有效的防护
  • Spring boot 集成redis
  • centos | vscode | 更新迭代太快了吧!
  • No matching client found for package name ‘com.unity3d.player‘
  • 一文简介Maven初级使用
  • Kafka下载(kafka和jdk、zookeeper、SpringBoot的版本对应关系)
  • [C++] 如何使用Visual Studio 2022 + QT6创建桌面应用