Java 四种引用类型(强引用、软引用、弱引用、虚引用)
概述
Java 中的引用类似 C 语言中的指针,指向一个对象,比如:
// person 就是指向 Person 实例“张三”的引用
Person person = new Person("张三");
在 JDK1.2 以前,Java 里的引用是很传统的定义:如果 reference 类型的数据中存储的数值代表的是另外一块内存的起始地址,就称该 reference 数据是代表某块内存、某个对象的引用
这种定义当然没有什么不对,但现在看来显得太狭隘了,比如我们希望描述一类对象:当内存空间足够时,能保留在内存中,如果内存空间在进行了垃圾收集后仍然紧张,则可以抛弃这些对象,很多系统的缓存功能都符合这样的应用场景
JDK1.2 对引用的概念作了补充,将引用分为强引用(Strongly Reference)、软引用(SoftReference)、弱引用(Weak Reference)和虚引用(Phantom Reference),强度依次减弱
强引用
Java 中最常见的就是强引用,把一个对象赋给一个引用变量,这个引用变量就是一个强引用。类似 Object obj = new Object()
当一个对象被强引用变量引用时,除非超过了引用的作用域或者显示地将相应强引用赋值为 null,否则是不可能被垃圾回收器回收的
软引用
软引用用来描述一些有用但非必须的对象,此类对象只有在进行一次垃圾收集仍然没有足够内存时,才会在第二次垃圾收集时被回收,需要用 java.lang.ref.SoftReference 类来实现
public class SoftRefenenceDemo {
public static void main(String[] args) {
softRefMemoryEnough();
System.out.println("------------");
softRefMemoryNotEnough();
}
private static void softRefMemoryEnough() {
Object o1 = new Object();
SoftReference<Object> s1 = new SoftReference<Object>(o1);
System.out.println(o1); // java.lang.Object@2503dbd3
System.out.println(s1.get()); // java.lang.Object@2503dbd3
o1 = null;
System.gc();
System.out.println(o1); // null
System.out.println(s1.get()); // java.lang.Object@2503dbd3
}
/**
* JVM配置 -Xms5m -Xmx5m ,故意 new 一个大对象,使内存不足产生 OOM,看软引用回收情况
*/
private static void softRefMemoryNotEnough() {
Object o1 = new Object();
SoftReference<Object> s1 = new SoftReference<Object>(o1);
System.out.println(o1); // java.lang.Object@4b67cf4d
System.out.println(s1.get()); // java.lang.Object@4b67cf4d
o1 = null;
try {
byte[] bytes = new byte[10 * 1024 * 1024];
} catch(Error e) {
e.printStackTrace();
}
System.out.println(o1); // null
System.out.println(s1.get()); // null
}
}
弱引用
弱引用用来描述那些非必须对象,但它的强度比软引用更弱一些。被软引用关联的对象只能生存到下一次垃圾收集发生为止,当垃圾收集器开始工作,无论当前内存是否足够,都会回收掉只被弱引用关联的对象,需要用 java.lang.ref.WeakReference 类来实现
public class WeakReferenceDemo {
public static void main(String[] args) {
Object o1 = new Object();
WeakReference<Object> w1 = new WeakReference<Object>(o1);
System.out.println(o1); // java.lang.Object@7440e464
System.out.println(w1.get()); // java.lang.ref.WeakReference@49476842
o1 = null;
System.gc();
System.out.println(o1); // null
System.out.println(w1.get()); // null
}
}
虚引用
虚引用,顾名思义,就是形同虚设,与其他几种引用都不太一样,一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用必须和引用队列(RefenenceQueue)联合使用。虚引用的主要作用是跟踪对象垃圾回收的状态,仅仅是提供了一种确保对象被 finalize 以后,收到一个系统通知或者后续添加进一步的处理
public class PhantomReferenceDemo {
public static void main(String[] args) throws InterruptedException {
Object o1 = new Object();
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();
PhantomReference<Object> phantomReference = new PhantomReference<Object>(o1,referenceQueue);
System.out.println(o1); // java.lang.Object@7440e464
System.out.println(referenceQueue.poll()); // null
System.out.println(phantomReference.get()); // null
o1 = null;
System.gc();
Thread.sleep(3000);
System.out.println(o1); // null
System.out.println(referenceQueue.poll()); // java.lang.ref.PhantomReference@49476842
System.out.println(phantomReference.get()); // null
}
}
ReferenceQueue 是用来配合引用工作的,没有ReferenceQueue 一样可以运行。SoftReference、WeakReference、PhantomReference 都有一个可以传递 ReferenceQueue 的构造器。创建引用的时候,可以指定关联的队列,当 GC 释放对象内存的时候,会将引用加入到引用队列。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动,这相当于是一种通知机制。当关联的引用队列中有数据的时候,意味着指向的堆内存中的对象被回收。通过这种方式,JVM 允许我们在对象被销毁后,做一些我们自己想做的事情
Java 四种引用类型(强引用、软引用、弱引用、虚引用)的更多相关文章
- java中四种引用类型(对象的强、软、弱和虚引用)
对象的强.软.弱和虚引用在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2 ...
- Java中四种引用:强、软、弱、虚引用
这篇文章非常棒:http://alinazh.blog.51cto.com/5459270/1276173 Java中四种引用:强.软.弱.虚引用 1.1.强引用当我们使用new 这个关键字创建对象时 ...
- Java对象的强、软、弱和虚引用+ReferenceQueue
Java对象的强.软.弱和虚引用+ReferenceQueue 一.强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.当内存空间不足 ...
- Java:对象的强、软、弱、虚引用
转自: http://zhangjunhd.blog.51cto.com/113473/53092 1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无 ...
- Java:对象的强、软、弱和虚引用
1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK ...
- Java对象的强、软、弱和虚引用详解
1.对象的强.软.弱和虚引用 转自:http://zhangjunhd.blog.51cto.com/113473/53092/ 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无 ...
- java基础知识再学习--集合框架-对象的强、软、弱和虚引用
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://zhangjunhd.blog.51cto.com/113473/53092 本文 ...
- Java对象的强、软、弱和虚引用原理+结合ReferenceQueue对象构造Java对象的高速缓存器
//转 http://blog.csdn.net/lyfi01/article/details/6415726 1.Java对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变 ...
- Java:对象的强、软、弱和虚引用[转]
原文链接:http://zhangjunhd.blog.51cto.com/113473/53092/ 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法 ...
- Java:对象的强、软、弱和虚引用的区别
1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK ...
随机推荐
- 🔥🔥你真的知道TCP协议中的序列号确认、上层协议及记录标识问题吗?
引言 在前面的内容中,我们已经详细讲解了一系列与TCP相关的面试问题.然而,这些问题都是基于个别知识点进行扩展的.今天,我们将重点讨论一些场景问题,并探讨如何解决这些问题. 序列号确认问题 当A主机与 ...
- 龙芯发布 .NET 8 SDK 8.0.100-rc2 LoongArch64
随着.NET 8的发布的临近,国内的社区朋友们也很关心龙芯.NET 团队对于Loongarch .NET 8的发布时间,目前从龙芯.NET编译器团队的可靠信息,Loongarch .NET 8的发布会 ...
- Streamlit 快速构建交互式页面的python库
基础介绍 streamlit 是什么 Streamlit是一个面向机器学习和数据科学团队的开源应用程序框架,通过它可以用python代码方便快捷的构建交互式前端页面.streamlit特别适合结合大模 ...
- 2021年前端面试题——JS
目录: DOM事件流有那些阶段? 解释事件冒泡以及如何阻止它? 事件委派/事件委托是什么? 如何理解 JS 中的this关键字? 更改this指向的方法有那些? apply.call.bind 区别? ...
- 数据仓库主流开发语言——SQL
数仓开发语言概述 SQL语言介绍 数仓与SQL 结构化数据 二维表结构 SQL语法分类
- 【源码系列#04】Vue3侦听器原理(Watch)
专栏分享:vue2源码专栏,vue3源码专栏,vue router源码专栏,玩具项目专栏,硬核推荐 欢迎各位ITer关注点赞收藏 语法 侦听一个或多个响应式数据源,并在数据源变化时调用所给的回调函数 ...
- NLP复习之向量语义
向量语义 词汇语义 语义概念(sense or concept)是单词含义(word sense)的组成部分,词原型可以是多义的. 同义词是指:在某些或者全部的上下文中,单词之间有相同或近似含义 可能 ...
- --{module_name}_binary_host_mirror和--{module_name}_binary_site
--{module_name}_binary_host_mirror和--{module_name}_binary_site demo // .npmrc文件 sass_binary_site=htt ...
- 通过印模生成电子印章-Java源代码
以下代码是处理印模图片的核心代码,通过以下代码可以将公章图片转换为电子印章图片. 制作方式分为四步: 1.在白纸上加盖印章: 2.把加盖印章的白纸扫描,形成图片: 3.将图片通过下面的代码进行自动透明 ...
- CentOS安装openGauss2.0.1
CentOS安装openGauss2.0.1 OpenGauss是一款开源关系型数据库管理系统,采用木兰宽松许可证v2发行.openGauss内核源自PostgreSQL,深度融合华为在数据库领域多年 ...