JVM四种引用

97 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情
请思考,以下这句话是否正确?
“如果一个对象存在着指向它的引用,那么这个对象会不会被GC回收?”
回答这个问题需要搞懂什么是“引用”。
一般理解引用存放的是对象的内存地址,我们可以使用引用来操作对象。
更细一点引用一共有四个级别,根据引用的强弱关系,从高到低依次是强引用、软引用、弱引用和虚引用。
因此我们可以从它是什么类型引用来回答
今天学习遇到了强引用,弱引用,于是开始了百度之旅,下面是我个人的一些理解

定义上:

强引用:强引用是所有引用级别中最高的一个,也是我们最常使用的引用类型。我们平时通过new构造出来的对象,就是被强引用所指向的。

Object obj = new Object(); 
//只要obj还指向Object对象,Object对象就不会被回收
obj = null; //手动置null

软引用:强引用对象必须等到引用值为 null 或者作用域结束后才会能被回收,因此软引用应运而生。
当JVM的内存足够时,GC对待软引用和强引用的方式是一样,即不会主动回收软引用对象;但当JVM的内存不足时,GC就会去主动回收软引用对象,
如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常。这种特性常常被用来实现缓存技术,比如网页缓存,图片缓存等。
弱引用:当GC进行垃圾回收时,无论是否当时JVM的内存是否充足,都会去主动回收弱引用对象,是ava.lang.ref.WeakReferenc类
虚引用:虚引用在JDK中是指java.lang.ref.PhantomReference类,虚引用也称为幻影引用或幽灵引用。虚引用是所有引用级别中最低的一个,甚至于“是否使用虚引用对于一个对象本身来说都没有任何区别”,并且我们也无法通过虚引用来获取一个对象实例。
在 JDK1.2 之后,用 PhantomReference 类来表示,它只有一个构造函数和一个 get() 方法,而且它的 get() 方法仅仅是返回一个null,也就是说将永远无法通过虚引用来获取对象,虚引用必须要和 ReferenceQueue 引用队列一起使用
作用:
1.重要对象回收监听 进行日志统计
2. 系统gc监听 因为虚引用每次GC都会被回收,那么我们就可以通过虚引用来判断gc的频率,如果频率过大,内存使用可能存在问题,才导致了系统gc频繁调用

使用上:

强引用:
顾名思义,强引用很强,强在“JVM即使内存溢出,也不会让GC去随便的回收强引用对象所占用的内存空间”。只有当强引用的值被置为 null 或作用域失效后,GC才会将强引用对象纳入被回收的范围。,正是由于这个缺点,所以我们引入了软引用。
我们可以从作用域的角度,将强引用分为局部变量和全局变量。

  • 强引用是局部变量 当方法结束时,方法中局部变量的作用域就失效。因此,当方法结束时,作为局部变量的强引用对象也就没了使用价值,之后就会等待被GC回收。
    当强引用的值被置为 null 时,也表明这个曾经的强引用对象已经不会再被使用,此时也会被纳入GC的回收范围内。
  • 强引用是全局变量 只有值为null时,作为全局变量的强引用对象才会等待被 GC 回收。

特点

强引用:GC时,永远不会被回收
软引用:内存不足时(自动触发GC),会被回收
弱引用:无论内存是否充足,只要进行GC,都会被回收
虚引用:如同虚设,和没有引用没什么区别