副标题#e#
一.这个常识呈现的目标是什么
办理内存泄露和OOM的问题
解公道的利用引用可以辅佐垃圾接纳器更好的打点Java内存
二.这个常识的应用场所是什么
在大概造成内存泄露的场景下
oom
因为软引用、弱引用、虚引用,不会和它关联的工具造成引用,所以不会对和他们关联的工具的生命周期发生影响。
出格留意,活着纪措施设计中一般很少利用弱引用与虚引用,利用软用的环境较多,这是因为软引用可以加快JVM对垃圾内存的接纳速度,可以维护系统的运行安详,防备内存溢出(OutOfMemory)等问题的发生。
三.这个常识的根基观念
1.强引用(StrongReference)
解强引用是我们在编程进程中利用的最简朴的引用,如代码String s=”abc”中变量s就是字符串工具”abc”的一个强引用。任何被强引用指向的工具都不能被垃圾接纳器接纳,这些工具都是在措施中需要的。
2.软引用(SoftReference)
解软引用是用来描写一些有用但并不是必须的工具,在Java顶用java.lang.ref.SoftReference类来暗示。对付软引用关联着的工具,只有在内存不敷的时候JVM才会接纳该工具。因此,这一点可以很好地用来办理OOM的问题,而且这个特性很适适用来实现缓存:好比网页缓存、图片缓存等。
解软引用可以和一个引用行列(ReferenceQueue)连系利用,假如软引用所引用的工具被JVM接纳,这个软引用就会被插手到与之关联的引用行列中。
3.弱引用(WeakReference)
解弱引用也是用来描写非必须工具的,当JVM举办垃圾接纳时,无论内存是否富裕,城市接纳被弱引用关联的工具。在java中,用java.lang.ref.WeakReference类来暗示。
4.虚引用(PhantomReference)
解虚引用和前面的软引用、弱引用差异,它并不影响工具的生命周期。在java顶用java.lang.ref.PhantomReference类暗示。假如一个工具与虚引用关联,则跟没有引用与之关联一样,在任何时候都大概被垃圾接纳器接纳。
解要留意的是,虚引用必需和引用行列关联利用,当垃圾接纳器筹备接纳一个工具时,假如发明它尚有虚引用,就会把这个虚引用插手到与之 关联的引用行列中。措施可以通过判定引用行列中是否已经插手了虚引用,来相识被引用的工具是否将要被垃圾接纳。假如措施发明某个虚引用已经被插手到引用行列,那么就可以在所引用的工具的内存被接纳之前采纳须要的动作。
四.一个demo
Demo2 { (String[] args) { String hello = String(); SoftReference sr = SoftReference(hello); hello = ; System..println(sr.()); String hello1 = String(); WeakReference<String> sr1 = WeakReference<String>(hello1); hello1 = ; System..println(sr1.()); System.gc(); System..println(sr1.()); ReferenceQueue<String> queue = ReferenceQueue<>(); String hello2 = String(); PhantomReference<String> pr = PhantomReference<>(hello2, queue); hello2 = ; System..println(pr.()); } }
五.一个应用场景
解下面举个例子,如果有一个应用需要读取大量的当舆图片,假如每次读取图片都从硬盘读取,则会严重影响机能,可是假如全部加载到内存傍边,又有大概造成内存溢出,此时利用软引用可以办理这个问题。
解设计思路是:用一个HashMap来生存图片的路径 和 相应图片工具关联的软引用之间的映射干系,在内存不敷时,JVM会自动接纳这些缓存图片工具所占用的空间,从而有效地制止了OOM的问题。在Android开拓中对付大量图片下载会常常用到。
下面这段代码是摘自博客:
http://blog.csdn.net/arui319/article/details/8489451
..... Map<String, SoftReference<Bitmap>> imageCache = HashMap<String, SoftReference<Bitmap>>(); <br>.... (String path) { Bitmap bitmap = BitmapFactory.decodeFile(path); SoftReference<Bitmap> softBitmap = SoftReference<Bitmap>(bitmap); imageCache.put(path, softBitmap); } Bitmap (String path) { SoftReference<Bitmap> softBitmap = imageCache.(path); (softBitmap == ) { ; } Bitmap bitmap = softBitmap.(); bitmap; }
#p#副标题#e#
六.对付java引用的领略
1.Java引用与Java垃圾接纳机制的干系
#p#分页标题#e#
解当Java虚拟机(JVM)以为内存不足用的时候,会触发垃圾接纳操纵(GC),排除无用的工具,释放内存。但是如何判定一个工具是否是垃圾呢?个中的一个要领是计较指向该工具的引用数量,假如引用数量为0,那么该工具就为垃圾(Thread工具是破例),不然尚有用处,不能被接纳。可是假如把引用数为0的工具都接纳了,照旧不能满意内存需求怎么办?Java把引用分为4种范例,垃圾接纳器会实验接纳只有弱引用的工具。
解凭据一个工具的引用可达(Reachable)强度,由强到弱分为5类,如下:
强可达(Strong Reachable)
在一个线程内,无需引用直接可达,新建设的工具是强可达的。
软可达(Soft Reachable)
不是强可达的,可是通过一个软引用(SoftReference)可达。
弱可达(Soft Reachable)
既不是强可达也不是软可达,可是通过一个弱引用(WeakReference)可达。
虚可达(Phantom Reachable)
既不是强可达,不是软可达,也不是弱可达,可是通过一个虚引用(PhantomReference)可达。
不行达(Unreachable)
没有任何引用指向工具。
URL:http://www.bianceng.cn/Programming/Java/201608/50377.htm
较量好、容易领略的是Java垃圾接纳器会优先清理可达强度低的工具。别的有两个重要的点:
强可达的必然不会被清理
JVM担保抛出out of memory之前,清理所有的软引用工具
2.我的领略和感悟
引用是java中很是重要的观念,领略它对写出高质量的代码很是重要,不然写出的代码都是各类内存泄露、oom却不自知。而要想搞大白这个观念,需要对jvm有必然的相识,包罗内存分派和垃圾接纳。
局部变量不持有对外部工具(即外部工具分派的内存区域)的的引用,因为局部变量只在它的浸染区域内有效。
成员变量不必然持有对外部工具((即外部工具分派的内存区域))的引用,只有当成员变量是内部类的时候才会呈现这个问题,假如成员变量是界说在其他的文件中,不会发生内存泄露,要留意是否大概造成内存泄露的问题。内部类才会持有对外部类的引用。即:1 内部类工具的建设依赖于外部类工具;2 内部类工具持有指向外部类工具的引用。
引用的简朴领略:A a = new A(),java会在堆中分派一块区域,然后让位于栈中的引用a指向这块区域。
其实垃圾接纳机制存眷的是堆中的分派的一块区域是否还被其他引用变量指着,假如没有人指着,就可以接纳了。
String hello = String(); SoftReference sr = SoftReference(hello); hello = ; System..println(sr.());
如上代码所示,hello指向堆中分派一块内存,软引用也指向了这块内存,这是hello排除了这个指向,所以这块内存区域今朝只有软引用指向他,这个时候这块内存区域不会当即被接纳,除非JVM需要内存才会被接纳。
hello1 = (); WeakReference<> sr1 = WeakReference<>(hello1); hello1 = ; System.out.println(sr1.get());
如上代码所示,hello1指向堆中分派一块内存,软引用也指向了这块内存,这是hello1排除了这个指向,所以这块内存区域今朝只有弱引用指向他,当JVM举办垃圾接纳时,无论内存是否富裕,城市接纳这块内存区域。
ReferenceQueue ReferenceQueue(); hello2 (); PhantomReference pr PhantomReference(hello2, ); hello2 ; Systemoutprintln(prget());
如上代码所示,hello2指向堆中分派一块内存,软引用也指向了这块内存,这是hello2排除了这个指向,所以这块内存区域今朝只有虚引用指向他,而虚引用则跟没有引用与之关联一样,这块内存区域在任何时候都大概被垃圾接纳器接纳。
5. 今后我们再说工具是否被接纳,发起说身分派的区域是否被接纳,这样越发直指问题的焦点。