- 对象至少被一个强引用持有着。可一通过这个强引用使用堆上的这个对象
-
当一个对象处于不可见阶段时,说明程序本身不再持有该对象的任何强引用,虽然该这些引用仍然是存在着的。
-
这种情况下,该对象仍可能被JVM等系统下的某些已装载的静态变量或线程或JNI等强引用持有着,这些特殊的强引用被称为”GC root”。存在着这些GC root会导致对象的内存泄露情况,无法被回收。
-
简单说就是程序的执行已经超出了该对象的作用域了。
-
对象处于不可达阶段是指该对象不再被任何强引用所持有包括程序中的强引用和JVM系统下的强引用。
-
但是在实际中又会根据不同的引用产生不同的实际回收时间
强引用,软引用,弱引用,虚引用
- 从 JDK1.2 版本开始,把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。这四种级别由高到低依次为:强引用、软引用、弱引用和虚引用。
强引用(Strong Reference)
- 强引用就是我们经常使用的引用,其写法如下:
Object o = new Object();
特点:
-
只要还有强引用指向一个对象,垃圾收集器就不会回收这个对象。
-
显式地设置 o 为 null,或者超出对象的生命周期,此时就可以回收这个对象。具体回收时机还是要看垃圾收集策略。
-
在不用对象的时将引用赋值为 null,能够帮助垃圾回收器回收对象。比如 ArrayList 的 clear() 方法实现:
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
软引用(Soft Reference)
-
如果一个对象只具有软引用,在内存足够时,垃圾回收器不会回收它;如果内存不足,就会回收这个对象的内存。也就是大多数情况下他是fullGC回收的
-
使用场景:
-
图片缓存。图片缓存框架中,“内存缓存”中的图片是以这种引用保存,使得 JVM 在发生 OOM 之前,可以回收这部分缓存。
-
如果将浏览过的网页存储到内存中会造成内存的大量浪费,甚至会造成内存溢出这时候就可以使用软引用
Person person = new Person(20);
//软引用
SoftReference soft = new SoftReference<>(person);
if (soft.get() == null) {
System.out.println(“已经死亡”);
} else {
System.out.println(“还活着”);
Person person1 = soft.get();
System.out.println(person1);
}
弱引用(Weak Reference)
-
简单来说,就是将对象留在内存的能力不是那么强的引用。当垃圾回收器扫描到只具有弱引用的对象,不管当前内存空间是否足够,都会回收内存。
-
弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程, 因此不一定会很快发现那些只具有弱引用的对象。所以被软引用关联的对象只有在内存不足时才会被回收,而被弱引用关联的对象在JVM进行垃圾回收时总会被回收。
Person person = new Person(20);
//软引用
SoftReference soft = new SoftReference<>(person);
Person person1 = new Person(23);
//弱引用
WeakReference week = new WeakReference<>(person1);
//通知GC
System.gc();
Thread.sleep(1000);
if (soft.get() == null) {
System.out.println(“person: 软引用已经死亡”);
} else {
System.out.println(“person: 软引用还活着”);
System.out.println(soft.get());
}
if (week.get() == null) {
System.out.println(“person1: 弱引用已经死亡”);
} else {
System.out.println(“person1: 弱引用还活着”);
System.out.println(soft.get());
}
- 如果一个对象是偶尔的使用,并且希望在使用时随时就能获取到,但又不想影响此对象的垃圾收集,那么应该用 Weak Reference 来记住此对象。或者想引用一个对象,但是这个对象有自己的生命周期,你不想介入这个对象的生命周期,这时候就应该用弱引用,这个引用不会在对象的垃圾回收判断中产生任何附加的影响。
虚引用(Phantom Reference)
-
虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
-
无法通过虚引用来获取对一个对象的真实引用, 他的get永远是null。
-
虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。当发生GC,虚引用就会被回收,我们可以通过ReferenceQueue获得虚引用被回收的通知
Person obj = new Person(12);
ReferenceQueue refQueue = new ReferenceQueue<>();
PhantomReference phantomReference = new PhantomReference(obj,refQueue);
new Thread(new Runnable() {
@Override
小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
最后
现在正是金三银四的春招高潮,前阵子小编一直在搭建自己的网站,并整理了全套的**【一线互联网大厂Java核心面试题库+解析】:包括Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等**
(备注Java)**
[外链图片转存中…(img-iuBol0De-1710692642077)]
最后
现在正是金三银四的春招高潮,前阵子小编一直在搭建自己的网站,并整理了全套的**【一线互联网大厂Java核心面试题库+解析】:包括Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等**
[外链图片转存中…(img-NebjjbO9-1710692642078)]