Marvel-Site Marvel-Site
首页
  • Java

    • Java基础
    • Java进阶
    • Java容器
    • Java并发编程
    • Java虚拟机
  • 计算机基础

    • 数据结构与算法
    • 计算机网络
    • 操作系统
    • Linux
  • 框架|中间件

    • Spring
    • MySQL
    • Redis
    • MQ
    • Zookeeper
    • Git
  • 架构

    • 分布式
    • 高并发
    • 高可用
    • 架构
  • 框架

    • React
    • 其他
  • 实用工具
  • 安装配置

    • Linux
    • Windows
    • Mac
  • 开发工具

    • IDEA
    • VsCode
  • 关于
  • 收藏
  • 草稿
  • 索引

    • 分类
    • 标签
    • 归档
GitHub (opens new window)

Marvel

吾必当乘此羽葆盖车
首页
  • Java

    • Java基础
    • Java进阶
    • Java容器
    • Java并发编程
    • Java虚拟机
  • 计算机基础

    • 数据结构与算法
    • 计算机网络
    • 操作系统
    • Linux
  • 框架|中间件

    • Spring
    • MySQL
    • Redis
    • MQ
    • Zookeeper
    • Git
  • 架构

    • 分布式
    • 高并发
    • 高可用
    • 架构
  • 框架

    • React
    • 其他
  • 实用工具
  • 安装配置

    • Linux
    • Windows
    • Mac
  • 开发工具

    • IDEA
    • VsCode
  • 关于
  • 收藏
  • 草稿
  • 索引

    • 分类
    • 标签
    • 归档
GitHub (opens new window)
  • Java

    • Java基础

    • Java进阶

      • 类的初始化与对象的初始化
      • Object类
      • 深度理解字符串String
      • Integer创建对象分析
      • 从原理上分析 i = i++ 与 i = ++i
      • Comparable和Comparator的区别
      • 四种引用介绍
        • 1. 四种引用介绍
        • 2. 软引用
        • 3. 弱引用
        • 4. 虚引用
        • 5. 引用队列
      • 静态代理与动态代理
      • 位运算
    • Java容器

    • Java并发编程

    • Java虚拟机

    • 常见面试题

  • 计算机基础

  • 框架|中间件

  • 架构

  • 后端
  • Java
  • Java进阶
Marvel
2022-07-13
目录

四种引用介绍

# 四种引用介绍

# 1. 四种引用介绍

  • 强引用(Strong Reference):大部分的对象的引用都是强引用,new 出来的对象就是强引用类型,强引用的对象是必不可少的存在,垃圾回收不会回收这些对象,即使内存空间不足,jvm 宁可抛出 OutOfMemeryError 错误,使程序终止,也不会回收强引用对象。
  • 软引用(Soft Reference):当内存空间足够的时候,垃圾回收不会回收这些对象;当内存空间不足的时候,垃圾回收就会回收这些对象。使用SoftReference修饰。
  • 弱引用(Weak Reference):当进行垃圾回收是,不管内存是否足够,都会将弱引用对象进行回收。使用WeakReference修饰。通常用于实现对象的辅助数据结构,当对象不再被强引用引用时,可以通过弱引用来获取对象的相关信息。
  • 虚引用(Phantom Reference):他不能单独使用,必须和引用队列联合使用,虚引用主要用来跟踪对象被垃圾回收的活动。

# 2. 软引用

当内存空间足够的时候,垃圾回收不会回收这些对象;当内存空间不足的时候,垃圾回收就会回收这些对象。

🖥 代码

SoftReference<Object> softReference = new SoftReference<>(new Object());
System.out.println(softReference.get()); // 输出对象地址
try {
    byte[] bytes = new byte[30 *1024 *1024];
} finally {
    System.out.println(softReference.get());  // null
}
1
2
3
4
5
6
7

📃 使用场景

假如一个应用需要读取大量的图片,如果每次读取图片都从硬盘读取则会严重影响性能,如果一次性全部加载到内存中有可能造成内存溢出。

设计思路:用一个HashMap来保存图片的路径和相应图片对象关联的软引用之间的映射关系,在内存不足时,JVM会自动回收这些缓存图片对象占用的空间,从而有效避免了OOM的问题。

Map<String, SoftReference<Bitmap>> imageCache = new HashMap<>();

# 3. 弱引用

当进行垃圾回收是,不管内存是否足够,都会将弱引用对象进行回收。

🖥 代码

WeakReference<Object> weakReference = new WeakReference<>(new Object());
System.out.println(weakReference.get()); // 输出对象地址
System.gc();
System.out.println(weakReference.get()); // null
1
2
3
4

🌰 应用场景:WeakHashMap、ThreadLocal

WeakHashMap使用了弱引用,当entry键值对中的键不再被引用的时候,在垃圾回收的时候,这个entry就会被垃圾回收。

Integer key = new Integer(1);
String value = "s";

Map<Integer, String> map = new WeakHashMap<>();

map.put(key, value);
System.out.println(key); // 1
System.out.println(map); // {1=s}
System.out.println("-----------------------------");

key = null;
System.out.println(key); // null
System.out.println(map); // {1=s}
System.out.println("-----------------------------");

System.gc();
System.out.println(key); // null
System.out.println(map); // {}        如果是HashMap,这里就为{1=s}
System.out.println("-----------------------------");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

ThreadLocal 也同样应用了弱引用,TreadLocalMap 中的 Entry 的键就是弱引用。

static class Entry extends WeakReference<ThreadLocal<?>> {
    /** The value associated with this ThreadLocal. */
    Object value;

    Entry(ThreadLocal<?> k, Object v) {
        super(k);
        value = v;
    }
}
1
2
3
4
5
6
7
8
9

# 4. 虚引用

虚引用不会决定对象的生命周期,如果一个对象持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收,他不能单独使用,也不能通过它访问对象,虚引用必须和引用队列ReferenceQueue联合使用。

虚引用的作用是跟踪对象被垃圾回收的状态。仅仅提供了一种确保对象被finalize之后,做某些事情的机制。

ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
PhantomReference<Object> phantomReference = new PhantomReference<>(new Object(), referenceQueue);

System.out.println(phantomReference.get()); // null
System.out.println(referenceQueue.poll()); // null

System.out.println("----------------------------");
System.gc();
Thread.sleep(500);

System.out.println(phantomReference.get()); // null
System.out.println(referenceQueue.poll()); // java.lang.ref.PhantomReference@1b6d3586
1
2
3
4
5
6
7
8
9
10
11
12

构造时必须传入引用队列:

public PhantomReference(T referent, ReferenceQueue<? super T> q)
1

虚引用和引用队列关联使用,当垃圾回收器准备回收一个对象时,如果发现它还是虚引用,就会把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否要将垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,就可以在所引用的对象的内存被回收之前采取必要的行动。

# 5. 引用队列

对象被回收前需要被引用队列保存,下面以弱引用为例:

ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
WeakReference<Object> weakReference = new WeakReference<>(new Object(), referenceQueue);

System.out.println(weakReference.get());  // java.lang.Object@1b6d3586
System.out.println(referenceQueue.poll()); // null

System.out.println("----------------------------");
System.gc();
Thread.sleep(500);

System.out.println(weakReference.get()); // null
System.out.println(referenceQueue.poll()); // java.lang.ref.WeakReference@4554617c
1
2
3
4
5
6
7
8
9
10
11
12

引用和引用队列的继承关系

image-20220621202655619
编辑 (opens new window)
#Java
上次更新: 2024/04/17, 21:30:18
Comparable和Comparator的区别
静态代理与动态代理

← Comparable和Comparator的区别 静态代理与动态代理→

最近更新
01
位运算
05-21
02
二叉树
05-12
03
Spring三级缓存解决循环依赖
03-25
更多文章>
Theme by Vdoing | Copyright © 2022-2024 Marvel
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式