Java强引用、软引用、弱引用及虚引用深入探讨
强引用、软引用、弱引用和虚引用深入探讨
为了更灵活的控制对象的生命周期,在JDK1.2之后,引用被划分为强引用、软引用、弱引用、虚引用四种类型,每种类型有不同的生命周期,它们不同的地方就在于垃圾回收器对待它们会使用不同的处理方式。
引用类型在日常开发中并不常关注,也很少注意到,因此很多人忽略了它们的存在,而事实上,引用类型在Java体系中扮演着十分重要的角色,要想对Java体系有一个更深层次的理解,了解和掌握这些引用的用法是十分必要的。
在正式开始前,我们先来上两道开胃菜。
为什么需要回收
每一个Java程序中的对象都会占用一定的计算机资源,最常见的,如:每个对象都会在堆空间上申请一定的内存空间。但是除了内存之外,对象还会占用其它资源,如文件句柄,端口,socket等等。当你创建一个对象的时候,必须保证它在销毁的时候会释放它占用的资源。否则程序将会在OOM中结束它的使命。
在Java中不需要程序员来管理内存的分配和释放,Java有自动进行内存管理的神器——垃圾回收器,垃圾回收器会自动回收那些不再使用的对象。
在Java中,不必像C或者C++那样显式去释放内存,不需要了解其中回收的细节,也不需要担心会将同一个对象释放两次而导致内存损坏。所有这些,垃圾回收器都自动帮你处理好了。你只需要保证那些不再被使用的对象的所有引用都已经被释放掉了,否则,你的程序就会像在C++中那样结束在内存泄漏中。
虽然垃圾回收器确实让Java中的内存管理比C、C++中的内存管理容易许多,但是你不能对于内存完全不关心。如果你不清楚JVM到底会在什么条件下才会对对象进行回收,那么就有可能会不小心在代码中留下内存泄漏的bug。
因此,关注对象的回收时机,理解JVM中垃圾收集的机制,可以提高对于这个问题的敏感度,也能在发生内存泄漏问题时更快的定位问题所在。想了解更多关于垃圾回收相关的细节,可以参考这篇文章。
为什么需要引用类型
引用类型是与JVM密切合作的类型,有些引用类型甚至允许在其引用对象在程序中仍需要的时候被JVM释放。
那么,为什么需要这些引用类型呢?
在Java中,垃圾回收器线程一直在默默的努力工作着,但你却无法在代码中对其进行控制。无法要求垃圾回收器在精确的时间点对某些对象进行回收。
有了这些引用类型之后,可以一定程度上增加对垃圾回收的粒度把控,可以让垃圾回收器在更合适的时机回收掉那些可以被回收掉的对象,而并不仅仅是只回收不再使用的对象。
这些引用类型各有特点,各有各的适用场景,清楚的了解和掌握它们的用法可以帮助你写出更加健壮的代码。
说明
在JDK 1.2以前的版本中,如果一个对象没有被任何变量引用,那么程序就无法再使用这个对象。也就是说,只有当对象处于可达(reachable)状态时,程序才能使用它。只有在对象没有任何其他对象引用它时,垃圾回收器才会对它进行收集。对象只有被引用和没有被引用两种状态。这种方式无法描述一些“食之无味,弃之可惜”的对象。
而很多时候,我们希望存在这样一些对象:当内存空间足够时,可以将它们保存在内存中,不进行回收;当内存空间变得紧张时,允许JVM回收这些对象。大部分缓存都符合这样的场景。
从JDK 1.2版本开始,Java对引用的概念进行了扩充,对象的引用分成了4种级别,从而使程序开发者能更加灵活地控制对象的生命周期,更好的控制创建的对象何时被释放和回收。
这4种级别由高到低依次为:强引用、软引用、弱引用和虚引用。
实力翻车
欢迎来到大型翻车现场,接下来将实力演示一波因为强引用过多导致的翻车例子。
如果你需要在整个程序运行期间保存一些对象(因为它们的初始化很耗费时间和资源),你可能会使用静态集合对象来存储并且在代码中随处使用它们。
public static Map<K, V> storedObjs = new HashMap<>();
但是这样,就会阻止垃圾回收器对集合中的对象进行回收和销毁。从而可能导致OOM的发生。例如:
public class OOMTest {
public static List<Integer> cachedObjs = new ArrayList<>();
public static void main(String[] args) {
for (int i = 0; i < 100_000_000; i++) {
cachedObjs.add(i);
}
}
}
输出如下:
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
这样就符合预期的翻车了。但你也许会说,谁会这么无聊,创建这么多变量。
嗯,确实是的,但是别忘了,一个程序可能会运行很长时间,几个月,甚至几年(如果你的代码和公司足够健壮的话),如果期间不断的创建变量而不清理的话(像上面那样把HashMap当缓存使用),是有可能会导致这种情况发生的。
内容编排
接下来的文章将从以下几方面对这四种引用进行介绍:
- 简要介绍
- 源码剖析
- 总结
注意 本系列文章都是以
JDK1.8
版本的代码进行分析,不同版本中代码会略有差异。
如果只是想要对这些引用进行简单了解,那么看完简要介绍部分即可,如果想要有更深入的研究,可以继续查阅源码剖析部分。
Java强引用、软引用、弱引用及虚引用深入探讨的更多相关文章
- GC真正的垃圾:强、软、弱、和虚 对象
垃圾回收的基本思想就是判断一个对象是否可触及性,说白了就是判断一个对象是否可以访问,如果对象对引用了,说明对象正在被使用,如果发现对象没有被引用,说明对象已经不再使用了,不再使用的对象可以被回收,但是 ...
- Java强,软,弱,虚类型
链接 http://wiseideal.iteye.com/blog/1469295
- 0030 Java学习笔记-面向对象-垃圾回收、(强、软、弱、虚)引用
垃圾回收特点 垃圾:程序运行过程中,会为对象.数组等分配内存,运行过程中或结束后,这些对象可能就没用了,没有变量再指向它们,这时候,它们就成了垃圾,等着垃圾回收程序的回收再利用 Java的垃圾回收机制 ...
- Java:对象的强、软、弱、虚引用
转自: http://zhangjunhd.blog.51cto.com/113473/53092 1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无 ...
- Java中四种引用:强、软、弱、虚引用
这篇文章非常棒:http://alinazh.blog.51cto.com/5459270/1276173 Java中四种引用:强.软.弱.虚引用 1.1.强引用当我们使用new 这个关键字创建对象时 ...
- 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/ 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法 ...
随机推荐
- PHP画矩形,椭圆,圆,画椭圆弧 ,饼状图
1:画矩形: imagerectangle ( resource $image , int $x1 , int $y1 , int $x2 , int $y2 , int $col ) imagere ...
- Python项目代码结构
目录结构组织方式 简要解释一下: bin/: 存放项目的一些可执行文件,当然你可以起名script/之类的也行. luffy/: 存放项目的所有源代码.(1) 源代码中的所有模块.包都应该放在此目录. ...
- The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar报错
缺少jstl依赖解析xml文件,报错jaspException 添加依赖如下: <dependency> <groupId>jstl</grou ...
- 理解数据库连接池和ThreadLocal实现的事务控制
我发现 不少人 误解了这两者. csdn上也有人提出过这种疑问: http://bbs.csdn.net/topics/250061733 经过查阅资料和认真分析,我特说明一下这两者概念上的区别. 我 ...
- 课程五(Sequence Models),第一 周(Recurrent Neural Networks) —— 2.Programming assignments:Dinosaur Island - Character-Level Language Modeling
Character level language model - Dinosaurus land Welcome to Dinosaurus Island! 65 million years ago, ...
- cropper实现图片剪切上传
一.引入文件 <script src="jquery.min.js"></script> <link rel="stylesheet&quo ...
- TCP/IP 笔记 - TCP连接管理
TCP是一种面向连接的单播协议,在发送数据之前,通信双方必须在彼此建立一条连接:这与UDP的无连接不同,UDP无需通信双方发送数据之前建立连接.所有TCP需要处理多种TCP状态时需要面对的问题,比如连 ...
- MongoDB调优-查询优化-MongoDB Profiler
MongoDB查询优化-MongoDB Profiler MongoDB Profiler 概述 官方文档:https://docs.mongodb.com/manual/tutorial/manag ...
- 解决Android Studio 3.x版本的安装时没有SDK,运行时出现SDK tools错误
好久没更新了,最近手机上的闹钟APP没一个好用的,所以想自己写个. 那Android开发环境搭起来,注意先装好jdk. 1.安装Android Studio google的Android开发网站已经有 ...
- 区块链 + 大数据:EOS存储
谈到区块链的存储,我们很容易联想到它的链式存储结构,然而区块链从比特币发展到今日当红的EOS,技术形态已经演化了10年之久.目前的EOS的存储除了确认结构的链式存储以外,在状态存储方面有了很大的进步, ...