程序员

聊聊JVM系列一 对象死了吗?

2020-12-25  本文已影响0人  星期三不上班

程序员:我辛辛苦苦创建的对象,GC你却把他回收了,你还我对象还我对象;

GC:好啊,摘下星星给你,摘下月亮给你,摘下太阳给你,你要的都给你, 于是 -> java.lang.OutOfMemoryError:PermGen space ......

作为一个心地善良正直勇敢的程序员,删过库,跑过路,我害怕一个小小的内存溢出,老板,服务器内存不够了,再来100个G

你知道的,JVM作为程序员的好伙伴,我们一般不会关心他默默为我们做了那些事情,他像水一样无形的存在,除非下大雨发了洪水(OutOfMemoryError:PermGen 一类的状况)我们才发现,哦,原来他这么厉害啊,于是就紧急着翻书,百度,谷歌各种错误,寻求解决之道,这篇文章就是来聊聊和我们平时默默打交道JVM如何判断对象已死.

先来看张图:
image

<figcaption style="box-sizing: border-box; outline: 0px; display: block; text-align: center; margin: 8px; color: rgb(153, 153, 153); font-size: 14px; overflow-wrap: break-word;">对象引用状态图</figcaption>

了解对象的引用状态可以帮助你了解GC回收的时候是如何回收的,回收那些对象,怎么判断对象死没死!

特点:软引用通过SoftReference类实现。 软引用的生命周期比强引用短一些。只有当 JVM 认为内存不足时,才会去试图回收软引用指向的对象:即JVM 会确保在抛出 OutOfMemoryError 之前,清理软引用指向的对象。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。后续,我们可以调用ReferenceQueue的poll()方法来检查是否有它所关心的对象被回收。如果队列为空,将返回一个null,否则该方法返回队列中前面的一个Reference对象。

应用场景:软引用通常用来实现内存敏感的缓存。如果还有空闲内存,就可以暂时保留缓存,当内存不足时清理掉,这样就保证了使用缓存的同时,不会耗尽内存。

特点:虚引用也叫幻象引用,通过PhantomReference类来实现。无法通过虚引用访问对象的任何属性或函数。幻象引用仅仅是提供了一种确保对象被 finalize 以后,做某些事情的机制。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。

ReferenceQueue queue = new ReferenceQueue ();PhantomReference pr = new PhantomReference (object, queue); 

程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取一些程序行动。
** 应用场景**:可用来跟踪对象被垃圾回收器回收的活动,当一个虚引用关联的对象被垃圾收集器回收之前会收到一条系统通知。

简单总结一下:强引用就像大老婆,关系很稳固。
软引用就像二老婆,随时有失宠的可能,但也有扶正的可能。
弱引用就像情人,关系不稳定,可能跟别人跑了。
幻像引用就是梦中情人,只在梦里出现过。

知道了各个对象的引用关系,那么GC是何时进行回收呢,这里有一个算法叫做<u style="box-sizing: border-box; outline: 0px; overflow-wrap: break-word;">可达性分析算法</u>,敲黑板,划重点了,期末考试要考,该算法的基本思路就是通过一些被称为引用链(GC Roots)的对象作为起点,从这些节点开始向下搜索,搜索走过的路径被称为(Reference Chain),当一个对象到GC Roots没有任何引用链相连时(即从GC Roots节点到该节点不可达),则证明该对象是不可用的。看图:

image
如上图所示,object1~object4对GC Root都是可达的,说明不可被回收,object5~object7对GC Root节点不可达,说明其可以被回收。

在Java中,可作为GC Root的对象包括以下几种:

上一篇 下一篇

猜你喜欢

热点阅读