详解Java中对象的软、弱和虚引用的区别
对于大部分的对象而言,程序里会有一个引用变量来引用该对象,这是最常见的引用方法。除此之外,java.lang.ref包下还提供了3个类:SoftReference、WeakReference和PhantomReference。它们分别代表了系统对对象的另外3中引用方式:软引用、弱引用和虚引用。
Java中四种引用的区别和关联:
- 强引用。这是Java中最常见的引用方式。程序创建一个对象,并把这个对象赋给一个引用变量,程序通过该引用变量来操作实际的对象。当一个对象被一个或者多个引用变量引用时,它处于可达状态,不能被系统垃圾回收机制回收。
- 软引用。当一个对象只有软引用时,它有可能被垃圾回收机制回收。对于只有软引用的对象而言,当系统内存空间足够时,它不会被系统回收,程序也可以使用该对象。当系统内存空间不足时,系统可能会回收它。软引用通常用于对内存敏感的程序中。
- 弱引用。弱引用和软引用很像,但它的级别比软引用更低。对于只有弱引用的对象而言,当系统垃圾回收机制运行时,不管系统内存是否足够,总会回收该对象所占用的内存。当然并不是说当一个对象只有软引用时,它会立即被回收,正如那些失去引用的对象一样,必须等到系统垃圾回收机制运行时才会被回收。
- 虚引用。虚引用完全类似于没有引用。虚引用对对象本身没有什么太大的影响。虚引用主要用于跟踪对象被垃圾回收的状态,虚引用不能单独使用,虚引用必须和引用队列(ReferenceQueue)搭配使用。
软、弱和虚引用都包含了一个get()方法,用于获取被它们所引用的对象。区别是虚引用的get()方法只会返回null。
引用队列由java.lang.ReferenceQueue类表示,它用于保存被回收后对象的引用。与软引用和弱引用不同的是,虚引用在对象被释放之前,将把它对应的虚引用添加到它关联的引用队列中,这使得可以在对象被回收之前采取行动。
下面的代码示范了弱引用所引用的对象被系统垃圾回收的过程:
import java.lang.ref.WeakReference;
public class Test{
public static void main(String[] args){
String str = new String("AmosH");
WeakReference wr = new WeakReference(str);
//建立弱引用,此弱引用指向"AmosH"字符串
//注意这里一定要使用new来创建一个字符串对象
//否则会该字符串会被保留在常量值而非堆内存中
str = null;
//切断"AmosH"字符串的强引用
System.out.println(wr.get());
//output "AmosH"
//此时弱引用依然有效
System.gc();
System.runFinalization();
//调用垃圾回收机制
System.out.println(wr.get());
//output null
//弱引用已经被回收
}
}
弱引用和软引用可以单独使用,但是虚引用不能单独使用。虚引用的主要作用是搭配引用队列来跟踪对象被垃圾回收的状态,程序可以通过检查与虚引用关联的引用队列中是否已经包含了该虚引用,从而了解虚引用所引用的对象是否即将被释放。
下面代码示范了虚引用对象被系统垃圾回收的过程:
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
public class Sample {
public static void main(String[] args){
String str = new String("AmosH");
ReferenceQueue rq = new ReferenceQueue();
//创建一个引用队列
PhantomReference pr = new PhantomReference(str,rq);
//创建一个虚引用,并且将该引用和rq引用队列关联
str = null;
//切断"AmosH"字符串的引用
System.out.println(pr.get());
//output null,因为系统无法通过虚引用的get()方法获取被引用对象
System.gc();
System.runFinalization();
//强制垃圾回收
System.out.println(rq.poll() == pr);
//output true
//虚引用被回收
}
}
使用这些引用类可以避免在程序执行期间将对象留在内存中。如果以软引用、弱引用和虚引用的方式引用对象,垃圾回收器就可以随意的释放对象。如果希望尽可能减小程序在其生命周期中所占用的内存大小时,这些引用类就会很有用处。
但是要注意的是,使用了这些特殊的引用类,就不能保留对对象的强引用,这会浪费这些引用类所提供的好处。
由于垃圾回收的不确定性,当程序希望从软、弱引用中获取被引用对象时,可能这个被引用对象已经被释放了。如果需要使用那个被引用的对象,则必须重新创建该对象:
obj = wr.get();
//获取引用所引用的对象
//如果被取出的对象为null
if(obj==null){
obj = recreateIt();
//重建该对象并使用一个强引用来引用它
//这里使用的伪代码,需要进行自定义
wr = new WeakReference(obj);
//重建这个弱引用
}
...//操作obj对象
obj = null;
//再次切断obj和对象之间的关系
详解Java中对象的软、弱和虚引用的区别的更多相关文章
- 详解Java中的clone方法
详解Java中的clone方法 参考:http://blog.csdn.net/zhangjg_blog/article/details/18369201/ 所谓的复制对象,首先要分配一个和源对象同样 ...
- java中的强,软,弱,虚引用
引用的应用场景 我们都知道垃圾回收器会回收符合回收条件的对象的内存,但并不是所有的程序员都知道回收条件取决于指向该对象的引用类型.这正是Java中弱引用和软引用的主要区别. 如果一个对象只有弱引用指向 ...
- Java:对象的强、软、弱和虚引用的区别
1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK ...
- 详解Java中的clone方法:原型模式
转:http://developer.51cto.com/art/201506/478985.htm clone顾名思义就是复制, 在Java语言中, clone方法被对象调用,所以会复制对象.所谓的 ...
- 详解Java中的clone方法 -- 原型模式
转自: http://blog.csdn.net/zhangjg_blog/article/details/18369201 Java中对象的创建 clone顾名思义就是复制, 在Java语言中, ...
- java中String是对象还是类?详解java中的String
有很多人搞不懂对象和类的定义.比如说java中String到底是对象还是类呢? 有人说String 既可以说是类,也可以说是对象. 其实他这么说也没问题, 类和对象其实都是一个抽象的概念. 我们可以把 ...
- JVM系列之:详解java object对象在heap中的结构
目录 简介 对象和其隐藏的秘密 Object对象头 数组对象头 整个对象的结构 简介 在之前的文章中,我们介绍了使用JOL这一神器来解析java类或者java实例在内存中占用的空间地址. 今天,我们会 ...
- 【Java学习笔记之三十三】详解Java中try,catch,finally的用法及分析
这一篇我们将会介绍java中try,catch,finally的用法 以下先给出try,catch用法: try { //需要被检测的异常代码 } catch(Exception e) { //异常处 ...
- 详解Java中的Object.getClass()方法
详解Object.getClass()方法,这个方法的返回值是Class类型,Class c = obj.getClass(); 通过对象c,我们可以获取该对象的所有成员方法,每个成员方法都是一个Me ...
随机推荐
- MySQL--自增列学习
##=====================================================================================## 在数据库表设计中会纠 ...
- Android 视频播放器 (二):使用MediaPlayer播放视频
在 Android 视频播放器 (一):使用VideoView播放视频 我们讲了一下如何使用VideoView播放视频,了解了基本的播放器的一些知识和内容.也知道VideoView内部封装的就是Med ...
- ActiveMQ 的安装与使用
消息中间件简介 消息中间件(MOM:Message Orient middleware) 消息中间件有很多的用途和优点: 1. 将数据从一个应用程序传送到另一个应用程序,或者从软件的一个模块传送到另外 ...
- pytorch bug: for step,data in enumerate(loader)+Connection reset by peer
单GPU跑的程序,而且是在docker中,迭代了几百步后,程序突然崩掉了, 程序停在了 for step,data in enumerate(loader),下面是部分bug信息 Traceback ...
- 运维笔记--ubuntu rm删除文件后 恢复
待补充 特别注意:umount分区,尝试恢复文件,文件夹(目录),全部文件 https://www.cnblogs.com/wangxiaoqiangs/p/5630288.html https:// ...
- .Net 并发写入文件的多种方式
1.简介 本文主要演示日常开发中利用多线程写入文件存在的问题,以及解决方案,本文使用最常用的日志案例! 2.使用File.AppendAllText写入日志 这是种常规的做法,通过File定位到日志文 ...
- Linux编程 19 编辑器(vim 用法)
一.概述 在开启shell脚本编程之前,必须要知道一款文本编辑器的用法,如文本编辑的查找,剪切,粘贴,定位等, 本篇只讲vim编辑器.vim编辑器全名叫vi improved,是经过对Unix系统vi ...
- mysql 开发进阶篇系列 4 SQL 优化(各种优化方法点)
1 通过handler_read 查看索引使用情况 如果索引经常被用到 那么handler_read_key的值将很高,这个值代表了一个行被索引值读的次数, 很低的值表明增加索引得到的性能改善不高,索 ...
- [工具向]__申请,下载,使用百度地图api
前言 api即应用程序接口,在我们的日常开发中,我们不仅可以在开源代码仓库(,github,码云)中获得很大的帮助,在日常开发中占重要地位的另一个东西就是api,我们可以使用众多的第三方编写的优秀的a ...
- BrainWeb: Simulated Brain Database使用说明
BrainWeb: Simulated Brain Database使用说明 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ BrainWeb: Sim ...