Java引用介绍与应用
2013-04-18 16:41
218 查看
注:本文作者是阿里巴巴B2B的谢中富;
前阵子在工作中遇到java.lang.Reference这个类,发现很多三方库中都用到这个类,如apache中的httpclient工具等,所以就找了一些资料了解了下。
本文主要介绍Java中SoftReference、WeakReference、PhantomReference这三种引用类型的作用以及与GC的关系。之后引用ibm社区上的一个例子说明WeakReference可以与GC配合防止应用中一些内存泄漏的问题。
中间如有理解不正确的地方,欢迎大家指正。
首先介绍下两个比较容易混淆的概念,引用和引用对象。
引用是指对象的引用,在代码中一般都是通过引用来获取对象实例进行数据操作;引用对象是指JDK中java.lang.ref包下的一些类,具体下文中有介绍。
强引用
在编码过程中最常见的就是这种用法如:
Object obj = new Object();
上面这段代码将在JVM堆中申请一块空间存储obj对象,只要obj引用存在,垃圾回收器就不会释放该空间。
GC根据一个对象是否可以通过强引用链可达来判断是否可以回收其内存。
在Java 1.2中引入了SoftReference、WeakReference、PhantomReference这三种引用对象,类结构关系如下图。
Reference是这三个引用对象的抽象基类。方法摘要如下:
当调用get()方法时可以返回一个强引用,如果返回null说明此引用已经被垃圾回收,所以也可以用这个方法来检测引用对象是否被垃圾回收。
SoftReference软可及引用对象
通常用来设计缓存,特点是被Soft Reference 引用的对象,要到JVM内存不足时且才会被GC回收,所以程序要允许此引用对象可空,不能强依赖于引用对象。此种类型的引用主要用于内存比较敏感的高速缓存。
WeakReference弱可及引用对象
此类型引用的生命周期要比SoftReference短。在每次GC时,一旦发现有WeakReference的引用,不管当前内存空间足够与否,都会回收此内存,即不会影响GC的策略。
PhantomReference虚可及引用对象(也称幽灵引用对象)
这个类只能用于跟踪被引用对象进行的收集。当GC确定了某个对象是虚可及对象时,此对象就被放在了它的ReferenceQueue上,表明引用对象已经结束,可以回收了。
JAVA对象的生命周期
再介绍下JAVA对象的生命周期,对上面的概念理解会有一定的帮助。在JVM里,对象整个生命周期分为以下七个阶段:
最常见的内存泄漏是用Map存储临时对象,如以下例子:
public class SocketManager {
/*想要在sokcet连接的时候传递用户信息,并在连接已经建立的时候拿到这个用户信息,下面的处理方式看似合理,
但是除非你确切知道socket什么时候被释放,并且同时把User引用从map中移除,否则map中的数据将永远不会被销毁,
只要程序的运行时间列长,最终会报out of memory*/
private Map<Socket,User> m = new HashMap<Socket,User>();
public void setUser(Socket s, User u) {
m.put(s, u);
}
public User getUser(Socket s) {
return m.get(s);
}
public void removeUser(Socket s) {
m.remove(s);
}
}
SocketManager socketManager;
......
socketManager.setUser(socket, user());
上面内存泄漏的例子主要是没有一种机制使socket与user的生命周期保持一致。利用WeakReference,就可以声明对象在生命周期中的依赖关系。
WeakHashMap的内部实现就是利用了WeakReference机制,value的引用依赖于key的生命周期,当key被释放时,value也将被释放。
利用WeakHashMap修改后的代码:
public class SocketManager {
private Map<Socket,User> m = new WeakHashMap<Socket,User>();
public void setUser(Socket s, User u) {
m.put(s, u);
}
public User getUser(Socket s) {
return m.get(s);
}
}
最后举一个ibatis cache的例子
上面cacheModel 中的reference-type属性可以设置以下三个值
WEAK,产生内存回收动作时,失效。
SOFT,内存不足时,失效。
STRONG,显式刷新时,失效。
reference-type 配置的是cache的缓存策略,这三种缓存策略的原理其实就是运用了Java中对应的引用对象机制。
http://www.artima.com/insidejvm/ed2/gcP.html
http://www.ibm.com/developerworks/java/library/j-jtp11225/
http://www.ibm.com/developerworks/java/library/j-jtp01246/index.html
一、前言
前阵子在工作中遇到java.lang.Reference这个类,发现很多三方库中都用到这个类,如apache中的httpclient工具等,所以就找了一些资料了解了下。本文主要介绍Java中SoftReference、WeakReference、PhantomReference这三种引用类型的作用以及与GC的关系。之后引用ibm社区上的一个例子说明WeakReference可以与GC配合防止应用中一些内存泄漏的问题。
中间如有理解不正确的地方,欢迎大家指正。
二、引用对象介绍
首先介绍下两个比较容易混淆的概念,引用和引用对象。引用是指对象的引用,在代码中一般都是通过引用来获取对象实例进行数据操作;引用对象是指JDK中java.lang.ref包下的一些类,具体下文中有介绍。
强引用
在编码过程中最常见的就是这种用法如:
Object obj = new Object();
上面这段代码将在JVM堆中申请一块空间存储obj对象,只要obj引用存在,垃圾回收器就不会释放该空间。
GC根据一个对象是否可以通过强引用链可达来判断是否可以回收其内存。
在Java 1.2中引入了SoftReference、WeakReference、PhantomReference这三种引用对象,类结构关系如下图。
Reference是这三个引用对象的抽象基类。方法摘要如下:
当调用get()方法时可以返回一个强引用,如果返回null说明此引用已经被垃圾回收,所以也可以用这个方法来检测引用对象是否被垃圾回收。
SoftReference软可及引用对象
通常用来设计缓存,特点是被Soft Reference 引用的对象,要到JVM内存不足时且才会被GC回收,所以程序要允许此引用对象可空,不能强依赖于引用对象。此种类型的引用主要用于内存比较敏感的高速缓存。
WeakReference弱可及引用对象
此类型引用的生命周期要比SoftReference短。在每次GC时,一旦发现有WeakReference的引用,不管当前内存空间足够与否,都会回收此内存,即不会影响GC的策略。
PhantomReference虚可及引用对象(也称幽灵引用对象)
这个类只能用于跟踪被引用对象进行的收集。当GC确定了某个对象是虚可及对象时,此对象就被放在了它的ReferenceQueue上,表明引用对象已经结束,可以回收了。
JAVA对象的生命周期
再介绍下JAVA对象的生命周期,对上面的概念理解会有一定的帮助。在JVM里,对象整个生命周期分为以下七个阶段:
三、利用WeakHashMap防止HashMap引起的内存泄漏
最常见的内存泄漏是用Map存储临时对象,如以下例子:public class SocketManager {
/*想要在sokcet连接的时候传递用户信息,并在连接已经建立的时候拿到这个用户信息,下面的处理方式看似合理,
但是除非你确切知道socket什么时候被释放,并且同时把User引用从map中移除,否则map中的数据将永远不会被销毁,
只要程序的运行时间列长,最终会报out of memory*/
private Map<Socket,User> m = new HashMap<Socket,User>();
public void setUser(Socket s, User u) {
m.put(s, u);
}
public User getUser(Socket s) {
return m.get(s);
}
public void removeUser(Socket s) {
m.remove(s);
}
}
SocketManager socketManager;
......
socketManager.setUser(socket, user());
上面内存泄漏的例子主要是没有一种机制使socket与user的生命周期保持一致。利用WeakReference,就可以声明对象在生命周期中的依赖关系。
WeakHashMap的内部实现就是利用了WeakReference机制,value的引用依赖于key的生命周期,当key被释放时,value也将被释放。
利用WeakHashMap修改后的代码:
public class SocketManager {
private Map<Socket,User> m = new WeakHashMap<Socket,User>();
public void setUser(Socket s, User u) {
m.put(s, u);
}
public User getUser(Socket s) {
return m.get(s);
}
}
四、引用的其它应用场景
最后举一个ibatis cache的例子<cacheModel id="SysConstants-Cache" type="MEMORY" readOnly="true" serialize="false"> <flushInterval hours="2" /> <property name="reference-type" value="SOFT" /> </cacheModel>
上面cacheModel 中的reference-type属性可以设置以下三个值
WEAK,产生内存回收动作时,失效。
SOFT,内存不足时,失效。
STRONG,显式刷新时,失效。
reference-type 配置的是cache的缓存策略,这三种缓存策略的原理其实就是运用了Java中对应的引用对象机制。
五、参考资料
http://www.artima.com/insidejvm/ed2/gcP.htmlhttp://www.ibm.com/developerworks/java/library/j-jtp11225/
http://www.ibm.com/developerworks/java/library/j-jtp01246/index.html
相关文章推荐
- Java引用介绍与应用
- 引用 Java自带的线程池ThreadPoolExecutor详细介绍说明和实例应用
- [转] 引用 Java自带的线程池ThreadPoolExecutor详细介绍说明和实例应用
- Java引用介绍 (r)
- java中强、软、弱和虚引用应用
- Java的浅拷贝与深拷贝及强引用、弱引用等引用介绍
- C#基类引用指向子类实例-虚方法的应用介绍
- 引用 JAVA EL表达式详细介绍使用手册
- Java中接口的应用 && 介绍
- Java学习笔记一:基本语法:类和对象的介绍、数组、引用类型
- Java 8新特性方法引用详细介绍
- java nio的介绍和应用
- 引用 JAVA标签库JSTL-EL表达式介绍使用配置手册
- VSS 在Java开发环境MyEclipse中的应用介绍
- JAX-RS介绍——Java API forRESTful WebServices,JAX-RS的目标是Web Services开发(这与HTML Web应用不同)而Spring MVC的目标则是Web应用开发
- java多线程应用中常用的sleep、yield、join、wait、notify、notifyAll方法介绍
- java中的四种引用介绍,强引用,软引用,弱引用,虚引用
- Java学习从入门到精通(二/八)应用、书籍介绍篇
- Java编程高手对CLASSPATH应用的详细介绍
- Java Socket应用(一)——java中网络基础介绍