最近研究Java Cache实现,发现使用到了软引用(SoftReference),不太理解,查阅了JDK文档、代码以及几篇文章。做个小结,如有错误,欢迎指正。
之所以想学习一下Java的几种引用类型,原因有两个:
理解Java Cache实现、学习Java引用与Java垃圾回收机制的关系
内存资源是有限的,需要合理的利用。Cache不是仅仅HashMap那么简单,Java引用与Java垃圾回收机制也有非常紧密的关系。
避免对Java引用的错误使用
某个同事把5000+交易数据放到一个HashMap里面,用一个Spring Singleton Bean的全局属性指向该HashMap。大量运用这种技术,很快就报out of memory。再大的内存也架不住对内存的错误使用。理解原理有助于我们尽量少犯或不犯低级错误。
Java引用与Java垃圾回收机制的关系
当Java虚拟机(JVM)觉得内存不够用的时候,会触发垃圾回收操作(GC),清除无用的对象,释放内存。可是如何判断一个对象是否是垃圾呢?其中的一个方法是计算指向该对象的引用数量,如果引用数量为0,那么该对象就为垃圾(Thread对象是例外),否则还有用处,不能被回收。但是如果把引用数为0的对象都回收了,还是不能满足内存需求怎么办?Java把引用分为4种类型,垃圾回收器会尝试回收只有弱引用的对象。
按照一个对象的引用可达(Reachable)强度,由强到弱分为5类,如下:
强可达(Strong Reachable)
在一个线程内,无需引用直接可达,新创建的对象是强可达的。
软可达(Soft Reachable)
不是强可达的,但是通过一个软引用(SoftReference)可达。
弱可达(Soft Reachable)
既不是强可达也不是软可达,但是通过一个弱引用(WeakReference)可达。
虚可达(Phantom Reachable)
既不是强可达,不是软可达,也不是弱可达,但是通过一个虚引用(PhantomReference)可达。
不可达(Unreachable)
没有任何引用指向对象。
比较好、容易理解的是Java垃圾回收器会优先清理可达强度低的对象。另外有两个重要的点:
强可达的一定不会被清理
JVM保证抛出out of memory之前,清理所有的软引用对象
兄弟连Java培训
分享以下4种Java引用
在实现一个缓存系统的时候,如果全部使用强引用,那么你需要自己去手动的把某些引用clear掉(引用置位null),否则迟早会抛出out of memory错误。缓存系统引入弱引用或者软引用的唯一原因是,把引用clear的事情交由Java垃圾回收器来处理,cache程序自己置身事外。
几种弱引用的使用方式非常相近。下面分别介绍4种引用类型。
强引用(StrongReference)
我们平时申明变量使用的就是强引用,普通系统99%以上都是强引用。比如,
String s = "Hello World"
弱引用(WeakReference)
垃圾回收器某个时刻决定回收软可达的对象的时候,会清理软引用,并可选的把引用存放到一个引用队列(ReferenceQueue)。
软引用(SoftReference)
类似弱引用,只不过Java虚拟机会尽量让软引用的存活时间长一些,迫不得已才清理。
虚引用(PhantomReference)
仅用来处理资源的清理问题,比Object里面的finalize机制更灵活。get方法返回的永远是null,Java虚拟机不负责清理虚引用,但是它会把虚引用放到引用队列里面。
两个测试例子
使用HashMap,会报out of memory错误。
[java] view
plain copy
public static void main(String[] args) {
Map<String, String> list = new HashMap<String, String>();
long i = 1;
while (i < 100000000L) {
list.put(
String.valueOf(i),
"JDJJDJJJJJJJJJJ%%%%%%%%JJJJJJJJJJJJJJJKKKKKKKKKKKKKKKKKJJJJJJ"
+ "JJJKKKKKHDDDJDJDJDJDJDJDJDJJDJDJDJDJDJDJJDJDJDJDJJDJDJJJJJJJJJ"
+ "JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ"
+ "JJJJJJJJJJJJJJJJJJJJJJJJJJJJ");
// 测试第一个是否依然存活
if (i % 100000 == 0) {
System.out.println(list.get(String.valueOf(1)));
}
i++;
}
}
使用WeakHashMap,不会报out of memory错误。
[java] view
plain copy
public static void main(String[] args) {
Map<String, String> list = new WeakHashMap<String, String>();
long i = 1;
while (i < 100000000L) {
list.put(
String.valueOf(i),
"JDJJDJJJJJJJJJJ%%%%%%%%JJJJJJJJJJJJJJJKKKKKKKKKKKKKKKKKJJJJJJ"
+ "JJJKKKKKHDDDJDJDJDJDJDJDJDJJDJDJDJDJDJDJJDJDJDJDJJDJDJJJJJJJJJ"
+ "JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ"
+ "JJJJJJJJJJJJJJJJJJJJJJJJJJJJ");
// 测试第一个是否依然存活
if (i % 100000 == 0) {
System.out.println(list.get(String.valueOf(1)));
}
i++;
}
}
小结
Java语言里面数组(Array)、列表(List)、Map等容器,对里面的每一个对象都有一个引用,大数据的情况下要小心内存泄露。弱引用只适合cache等特殊场景,对于那些一定不能Java让垃圾回收器回收的对象,要使用强引用。
分享到:
相关推荐
从JDK1.2版本开始,把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。这四种级别由高到低依次为:强引用、软引用、弱引用和虚引用。
1.强引用1.强引用 2.软引用(SoftReference) 3.弱引用(WeakReference) 4.虚引用(PhantomReference) 等等;
ava有四种引用类型,strongreference,softreference,weakreference,phantomreference。本篇文档主要的就是进阶的介绍和了解这四种引用类型的异同点,助于你对java的更好的学习理解
下面小编就为大家带来一篇浅谈Java中的四种引用方式的区别。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
本文会穿插大量的链接和引用。 建议先对Java、HTML、CSS、JS、ajax、HTTP、Firebug等有所了解。 推荐一下“菜鸟教程”(http://www.runoob.com/)中的相关教程(利 益无关~),很适 合入门。 linux下编写程序。 ...
浅谈java面向对象和引用,初学java的一些疑惑点
java thread的浅解析 如何创建线程
Java对象及引用是容易混淆却又必须掌握的基础知识,本章阐述Java对象和引用的概念,以及与其密切相关的参数传递。
深入浅出java、中文版,很简单,很生动
主要介绍了Java中四种引用类型详细介绍的相关资料,需要的朋友可以参考下
深入浅出-java.pdf java入门,适合未接触过java的童鞋
验证码破解的方法,简单验证码破解java示例
Java入门书籍 高清的 经典教材 比较不错 慢慢学习
详解Java解析XML的四种方法详解Java解析XML的四种方法详解Java解析XML的四种方法详解Java解析XML的四种方法详解Java解析XML的四种方法
JAVA 的五种引用类型及引用队列 在介绍 JAVA 的五种引用之前,先介绍一下什么是引用,以及引用和对象之间的关系 什么是引用 众所周知,JAVA 是一种面向对象的语言,在 JAVA 程序运行时,对象是存储在堆内存...
主要介绍了java四种引用及在LeakCanery中应用,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
多线程破解网站密码,适用于无任何保护措施的网站,如很多学校的教务系统。 需要txt的用户名文件和txt的字典文件,暴力破解。本源码仅供交流学习用。 适用说明: 先用火狐的firebug截取网站登录页面的post消息,将...
深入浅出java虚拟机,了解虚拟机的内部机制。。。。。。
使用Java 语言实现了Huffman编码的压缩和解压缩,能够实现对Ascii 文档的压缩和解压缩,目前尚不支持对二进制文档进行压缩
Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来模拟银行ATM...