Java 中的强引用、弱引用、软引用和虚引用

简介: 引用方式内存不足时垃圾回收机制启动时其余情况强引用否否否软引用是否否弱引用是是否虚引用可能可能可能在一般的程序中,弱引用和虚引用很少会被用到,强引用天天都在用就不必我说了,在有些情况下(如资源文件很大,但并不是全部要在同一时刻使用)我们会使用软引用来代替原来的强引用,一是可以避免某些情况下产生的 OOM,此外,它可以减少程序使用的内存,加速程序的运行。

一、继承结构

1.1 四大引用的继承关系

在 Java 中一共有四种引用类型,分别是强引用、弱引用、软引用和虚引用,其中,我们常用的是强引用,而其他三种引用都需要引入特定的 java.lang.ref 才能使用,他们的继承结构如下:

引用继承结构图image.gif编辑

一般只有强引用是直接使用的,而其他的三种引用都需要配合引用队列(ReferenceQueue)来使用会更好。

Java 中变量的类型有两大类,值类型和引用类型,这里的引用类型就是指可以引用的对象。在对引用类型进行操作时,我们实际只是得到了它的内存地址,通过内存地址来访问这个对象,并对其进行相关的操作,这和 C++ 的指针极为相似,但不完全相同。C++ 有基础数据类型的指针,而 Java 没有基础数据类型的引用,取而代之的是值类型。

1.2 引用和指针的关系

这里拓展和延伸一下,具体解释 C++ 中的指针、引用和 Java 的引用之间的区别和联系。

C++ 的指针

C++ 中的指针指向对象的内存地址,在参数传递时,以指针传递时只会将对象的内存地址传过去,在函数或方法内部再对地址进行访问以达到传参的目的。

Java 的引用

Java 中的引用和 C++ 中的指针类似,但是也不完全相同。Java 中的引用没有基础类型的引用,只能是引用类型,因此相比于 C++,没有 int 类型变量的地址一说,Java 只能得到引用类型的地址,无法得到基本数据类型的内存地址。

C++ 的引用

C++ 中也是有引用的,不过 C++ 的引用和指针以及 Java 的引用不同,它是变量或者对象的别名,和拷贝不一样,它是直接对原本的数据进行操作的。

二、四大引用方式

2.1 强引用(Reference)

使用强引用不需要引入任何包,Java 的引用方式默认就是强引用。

我们一般使用的引用都是强引用,当内存不足时,JVM 开始回收垃圾,但对于强引用的对象,JVM 不会对其进行回收,就算出现了 OOM(OutOfMemory),JVM 也不会对其进行回收,也就是说,强引用的对象是不会被 JVM 给回收的。这可以防止一些资源在程序运行的时候被回收了,当然,有利也有弊,当一些资源过大时,它们会占用大量的内存,甚至出现了 OOM 时,JVM 依然不会对其回收,这可能导致程序出现问题。在某些情况下,这会造成程序的内存泄露。

2.2 软引用(SoftReference)

使用软引用需要引入 java.lang.ref.SoftReference。

软引用不像强引用那么绝对,当内存不足时,JVM 就会尝试回收垃圾,而软引用的对象在这个时候就会被回收。不过,若没有达到内存不足的情况,JVM 不会回收软引用的对象。软引用的这个特性非常好,可以说它就是 Java 自动管理内存的标配,为什么这么说呢?我们知道,Java 是可以自动管理内存的,但在程序的运行过程中,JVM 是无法自动判断某些内存空间的,而这部分空间如果都是强引用对象且占用了很大的内存,甚至导致出现了 OOM,那么程序就出问题。这个时候,程序员就应该将其设定为软引用,告诉 JVM,这个对象在内存不足的时候是可以释放的。图片资源的缓存,网页资源的缓存中就大量使用了软引用。

2.3 弱引用(WeakReference)

使用弱引用需要引入 java.lang.ref.WeakReference。

弱引用,是一种比软引用还要“弱”的引用方式。当 Java 的垃圾回收机制开始运行时,弱引用的对象就会立刻被回收,无论内存是否充足。弱引用一般使用不多。

2.4 虚引用(PhantomReference)

使用虚引用需要引入 java.lang.ref.PhantomReference。

虚引用,顾名思义,其引用是虚的,并非真实的引用,因此可以认为这个对象没有任何引用,这个对象也无法通过虚引用被访问。虚引用对象在任何时候都可能被回收。虚引用可以理解为给这个对象打了个标记,程序员可以从中知道,这个对象要被回收或者已经被回收,虚引用的存在只是象征着这个对象曾经存在过。

三、总结

以上四种引用方式可以总结为下表:

引用方式 内存不足时 垃圾回收机制启动时 其余情况
强引用
软引用
弱引用
虚引用 可能 可能 可能

在一般的程序中,弱引用和虚引用很少会被用到,强引用天天都在用就不必我说了,在有些情况下(如资源文件很大,但并不是全部要在同一时刻使用)我们会使用软引用来代替原来的强引用,一是可以避免某些情况下产生的 OOM,此外,它可以减少程序使用的内存,加速程序的运行。

目录
相关文章
|
5月前
|
缓存 Java 程序员
Java面试题:解释强引用、软引用、弱引用和虚引用在Java中是如何工作的?
Java面试题:解释强引用、软引用、弱引用和虚引用在Java中是如何工作的?
40 1
|
6月前
|
缓存 Java 数据库连接
java面试题目 强引用、软引用、弱引用、幻象引用有什么区别?具体使用场景是什么?
【6月更文挑战第28天】在 Java 中,理解和正确使用各种引用类型(强引用、软引用、弱引用、幻象引用)对有效的内存管理和垃圾回收至关重要。下面我们详细解读这些引用类型的区别及其具体使用场景。
95 3
|
5月前
|
Java 运维
开发与运维引用问题之软引用又在Java特点如何解决
开发与运维引用问题之软引用又在Java特点如何解决
49 0
|
6月前
|
缓存 监控 算法
【Java】谈一谈虚引用
【Java】谈一谈虚引用
92 0
|
7月前
|
缓存 Java
【JAVA】强引用、软引用、弱引用、幻象引用有什么区别?
幻象引用:幻象引用是最弱的引用类型,几乎不影响对象的生命周期。它们主要用于在对象被回收前进行某些预处理操作,例如在对象被销毁时执行特定的清理任务。
64 0
|
7月前
|
Java
【JVM】深入理解Java引用类型:强引用、软引用、弱引用和虚引用
【JVM】深入理解Java引用类型:强引用、软引用、弱引用和虚引用
523 0
|
7月前
|
缓存 Java 程序员
Java垃圾回收: 什么是强引用、软引用、弱引用和虚引用?
Java垃圾回收: 什么是强引用、软引用、弱引用和虚引用?
79 2
|
算法 Java C++
14-理解Java中的不同引用类型:强引用、软引用、弱引用和虚引用
这篇文章将深入探讨Java中的四种引用类型:强引用、软引用、弱引用和虚引用。我们将逐一解释每种引用类型的特性和用途。
121 0
14-理解Java中的不同引用类型:强引用、软引用、弱引用和虚引用
|
Java C++
Java引用类型:强引用,软引用,弱引用,虚引用
Java引用类型:强引用,软引用,弱引用,虚引用
87 0
|
缓存 Java
【Java基础】java的引用类型(强引用,软引用,弱引用,虚引用)
【Java基础】java的引用类型(强引用,软引用,弱引用,虚引用)
152 0