Java中的引用类型(强引用、弱引用)和垃圾回收
Java中的引用类型和垃圾回收
强引用Strong References
强引用是最常见的引用:
比如:
StringBuffer buffer = new StringBuffer();
创建了一个StringBuffer类的对象,并用一个变量buffer存储对这个对象的引用。这就是个强引用。
变量持有的是这个对象的引用。通常,引用是一个对象的存储地址。
Java不像C或者C++一样,Java没有取地址符号&,也没有解引用符号*或者->。
引用不同于指针,引用不能与整形进行互相转换,也不能进行增减操作。
强引用是和垃圾回收机制相关的。
一般的,如果一个对象可以通过一系列的强引用引用到,那么就说明它是不会被垃圾回收机制(Garbage Collection)回收的。
因为垃圾回收是不会回收你正在使用的对象的。
垃圾回收机制Garbage Collection
如果一个对象,没有一个引用指向它,那么它就被认为是一个垃圾。
An object is considered garbage when there are no longer any references to it stored in any variables, the fields of any objects, or the elements of any arrays.
在某一个时间,garbage collector将会发现成为垃圾的对象,然后回收它所占用的内存。
C中用malloc()和free()来管理内存。
C++是用new和delete来分配和管理内存空间。
而Java使用garbage collection机制,不用程序员写代码管理,这样会有一些性能上的影响,因为garbage collector会主动地回收内存。
但是,GC机制减少了内存泄露,并且提高了程序员的效率。
什么时候强引用会太强了?
有时候应用会使用一些不能被继承的类,比如一个final的类,或者一个工厂方法返回的接口,并不知道有多少具体实现。
而我们想给这个类增加一个字段,比如给每一个对象一个序列号,于是我们用了HashMap,把这个类的对象作为key,一个序列号作为value。
这时候我们就必须100%确定地知道一个特定对象的序列号什么时候不再需要(比如对象的生命周期已经结束,就不再需要它的序列号属性),这样我们就可以从map中移除它的entry。
如果我们在应当移除引用的时候没有移除,垃圾回收将一直不会回收这个对象,引起内存泄露。
而如果我们过早地移除了我们还在使用的对象的引用,又会发现自己丢失了信息。
这些都是C/C++程序员经常会遇到的问题。而我们用的是Java,我们还要考虑这些,岂不是闹复杂了?
强引用另一个常见的问题是缓存问题。
比方说,图像的缓存。图像缓存应当阻止我们重复载入图像。
所以图像缓存保存有内存中已有的所有图像的引用,如果使用通常的强引用,强引用本身会使得图像一直存留在内存中,这样就使得程序员像上面一样,必须自己决定什么时候移除缓存中的引用,这样对象才能被垃圾回收机制回收。
这样你就又放弃了让GC自己管理垃圾回收的机制,而开始手动地管理内存。
引用对象类
Java的引用对象类在包java.lang.ref下。
http://docs.oracle.com/javase/7/docs/api/java/lang/ref/package-summary.html#package_description
其中包含了三种显式的引用类型(也即是Reference类的三个子类):
SoftReference
WeakReference
PhantomReference
一个引用对象(reference object)(即以上三种引用类型的对象)封装了一个对其他对象的引用(称作referent)。
引用对象提供了对referent的clean和get操作,但是不提供set操作。
引用对象本身可以像其他一般的对象一样被检查和操纵。
三种类型的引用定义了三种不同层次的可达性级别,由强到弱排列如下:
SoftReference > WeakReference > PhantomReference
越弱表示对垃圾回收器的限制越少,对象越容易被回收。
SoftReference
SoftReference用来实现一些内存敏感的缓存(Soft references are for implementing memory-sensitive caches),只要内存空间足够,对象就会保持不被回收。
反之,当宿主进程的内存空间不足时,对象就会被GC回收。
所以SoftReference意味着:hold on until you can’t.
WeakReference
WeakReference可以用来实现一些规范化映射(WeakHashMap),其中key或者value当它们不再被引用时可以自动被回收。
当你想引用一个对象,但是这个对象有自己的生命周期,你不想介入这个对象的生命周期,这时候你就是用弱引用。
这个引用不会在对象的垃圾回收判断中产生任何附加的影响。
PlantomReference
PlantomReference和WeakReference一样,也不会介入引用对象的生命周期。
PhantomReference用来调度一些预验清理动作,提供比Java清理机制更灵活的处理方式。(Phantom references are for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism.)
PlantomReference比较特殊,它的get方法总是返回null,所以你得不到它引用的对象。
它保存ReferenceQueue中的轨迹。
它允许你知道对象何时从内存中移除。
参考资料:
Java官方文档描述:
http://docs.oracle.com/javase/7/docs/api/java/lang/ref/package-summary.html
Android官方文档:
http://developer.android.com/reference/java/lang/ref/Reference.html
Stackoverflow上的讨论:
博文:
https://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html
http://java.dzone.com/articles/reference-types-java-part-1
http://zhang-xzhi-xjtu.iteye.com/blog/413159
http://blog.yohanliyanage.com/2010/10/ktjs-3-soft-weak-phantom-references/
书籍:
《Java in a nutshell》
http://docstore.mik.ua/orelly/java-ent/jnut/ch02_10.htm
Java中的引用类型(强引用、弱引用)和垃圾回收的更多相关文章
- 【Java讨论】引用类型赋值为null对加速垃圾回收的作用(转载)
:有一些人认为等于null可以帮助垃圾回收机制早点发现并标识对象是垃圾.其他人则认为这没有任何帮助.是否赋值为null的问题首先在方法的内部被人提起.现在,为了更好的阐述提出的问题,我们来撰写一个Wi ...
- Java中的内存泄露 和 JVM GC(垃圾回收机制)
一.什么是Java中的内存泄露? 在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点, 首先,这些对象是可达的,即在有向图中,存在通路可以与其相连:其次,这些对象是无用的,即程序以 ...
- java当中的强引用,软引用,弱引用,虚引用
强引用,软引用,弱引用,虚引用:不同的引用类型主要体现在GC上 强引用:如果一个对象具有强引用,它就不会被垃圾回收器回收.即使当前内存空间不足,JVM也不会回收它,而是抛出 OutOfMemoryEr ...
- Java -强引用&弱引用
⑴强引用(StrongReference) 就是通过new得的对象引用 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.当内存空间不足,Java虚拟机宁愿抛出OutOfMe ...
- Java 强引用 软引用 弱引用 虚引用详解
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt393 众所周知,java中是JVM负责内存的分配和回收,这是它的优点(使用方 ...
- java强引用 软引用 弱引用 虚引用
https://www.cnblogs.com/yw-ah/p/5830458.html Java四种引用包括强引用,软引用,弱引用,虚引用. 强引用: 只要引用存在,垃圾回收器永远不会回收Objec ...
- 详解Java中对象的软、弱和虚引用的区别
对于大部分的对象而言,程序里会有一个引用变量来引用该对象,这是最常见的引用方法.除此之外,java.lang.ref包下还提供了3个类:SoftReference.WeakReference和Phan ...
- JVM中强引用,弱引用,软引用和幽灵引用的代码
上代码: public class ReferenceTest { public static void main(String[] args) { //test1();//软引用 //test2() ...
- java中的引用类型:强软弱虚
java中的引用类型共4种:强软弱虚,具体每种类型的特点和应用场景.记录下.本文是看了马士兵老师的视频后记录整理的.加深印象. 基本概念 1. 强引用 强引用是使用最普遍的引用.如果一个对象具有强引用 ...
随机推荐
- android中AVD的使用
AVD路径设置 前面提到,不管用Eclipse还是从命令行创建Android Emulator时,相应的文件是被放置到 “C:\Documents and Settings\Administrator ...
- Windows Azure Cloud Service (11) PaaS之Web Role, Worker Role(上)
<Windows Azure Platform 系列文章目录> 本文是对Windows Azure Platform (六) Windows Azure应用程序运行环境内容的补充. 我们知 ...
- SQL Server 存储(5/8):理解IAM 页
在以前的文章里,我们讨论了数据页,GAM和SGAM,还有PFS页.今天我们一起来讨论下索引分配映射(Index Allocation Map:IAM)页. 在SQL Server 2005和以后的版本 ...
- js学习笔记(一)
1.数组实用方法大全 //给数组添加个方法,返回数组中的最大值 Array.prototype.max = function() { return Math.max.apply(null,this); ...
- 用2263份证件照图片样本测试how-old.net的人脸识别
上一年也就是这个时候微软根据自己的人脸识别API推出了一个识别照片中人脸年龄和性别的网站--http://how-old.net,小伙伴们各种玩耍,一年后的今天突发"奇想"地想测试 ...
- 原生JS查找元素
今天写了一个很简单.很粗暴的通过JS根据类来查找DOM元素. 为了降低它的粗暴等级(耗费性能)我给了三个等级. 首先性能最好的,适合FF,CH,IE8,通过querySelectorAll这个API. ...
- 如果你恨一个程序员,忽悠他去做iOS开发
如果你恨一个程序员,忽悠他去做iOS开发.不管他背景是cobel还是 java,送他一本iOS开发的书.这种书最好是国人写的,容易以偏概全一点,相比洋鬼子的书,更容易学到皮毛.这叫舍不得孩子套不着狼, ...
- 【C#】使用IExtenderProvider为控件添加扩展属性,像ToolTip那样
申明: - 本文适用于WinForm开发 - 文中的“控件”一词是广义上的说法,泛指包括ToolStripItem.MenuItem在内单个界面元素,并不特指继承自Control类的狭义控件 用过To ...
- 三星S4,呼转的来电,在来电界面上不显示的解决方案
因为工作关系,我有2个号码是呼叫转移到我现在的手机上的,如果有呼叫转移的来电的话,在通话界面里面没有提示该来电是呼叫转移来的.之前我用的诺基亚的,可以看到呼叫转移的来电,在号码的左边有个拐弯的箭头,提 ...
- js定时器的使用(实例讲解)
在javascritp中,有两个关于定时器的专用函数,分别为: 1.倒计定时器:timename=setTimeout("function();",delaytime);2.循环定 ...