欢迎回家
我们一直在改变

JAVA基础:强引用、软引用、弱引用、幻象引用 强引用、软引用、弱引用、幻象引用

问题:
强,软,弱,幻象引用是什么,他们之间的区别是什么?具体的使用场景是什么?

不同的引用其所代表的是对象的不同的可达性状态,这也影响到对象的GC。

强引用“Strong” Reference:
最常见的一种引用,平时对普通对象的引用就是强引用。比如 XX xx = new XX(); 对于一个普通的对象,如果没有其他的引用关系,那么当它超过引用的作用域,或者显示地将引用赋值为null,那么就可以被GC了。

软引用:
比强引用弱化一点,对于软引用的对象,只有当JVM认为内存不足时,才会去视图回收软引用指向的对象。所以,软引用一般用来实现内存敏感的缓存,当内存不足时,这部分缓存就会被清理掉而不会OOM。

弱引用:
比软引用更弱一点。无论内存够不够都无法避免被GC,主要用来构建一种没有特定约束的关系,在使用它时如果存在就用,不存在就重新实例化,也是很多缓存的实现方式。

幻象引用:
也就是虚引用,不能通过它访问对象。作用仅仅是提供一种确保对象被finalize以后做某些事情的机制。比如Psot-Mortem清理机制。也可以用幻象引用监控对象的创建和销毁。JAVA平台本身的Cleaner机制。

对于不同的引用,我们尝试用一张不算非常严谨的图来说明一下。
对象可达性变化图示:

图源自:极客时间JAVA 核心技术36讲。
图中各种引用导致的对象可达状态解释如下:

强可达:当一个对象可以有一个或多个线程 可以不通过各种引用访问到的情况。比如我们新建一个对象,那么创建它的线程就对它就是强可达。直接访问。
软可达:只要我们通过软引用才能访问到的对象
弱可达:无法通过强引用或者软引用访问,只有通过弱引用访问时的状态,这种状态非常接近finalize,当弱引用被清除的时候,就符合finalize条件了。
幻象可达:finalize以后的对象,并且其他引用都没有关联,只有幻象引用指向这个对象。
不可达:没有引用可以到达,这个对象可以被回收了。
所有引用类型都是抽象类java.lang.ref.Reference的子类。除了幻象引用,如果对象还没有被销毁,并且不是被幻象引用指向的,都可以用Reference类中的get()方法获取原有对象。这也意味着我们可以利用软引用或弱引用,访问指定对象,并让其重新指向强引用。(人为改变了对象的可达性状态)
引用应用编程举例:
引用队列多应用

Object counter = new Object();
ReferenceQueue refQueue = new ReferenceQueue<>();
PhantomReference p = new PhantomReference<>(counter, refQueue);
counter = null;
System.gc();
try {
// Remove 是一个阻塞方法,可以指定 timeout,或者选择一直阻塞
Reference ref = refQueue.remove(1000L);
if (ref != null) {
// do something
}
} catch (InterruptedException e) {
// Handle it
}
我们可以影响软引用的垃圾收集吗?可以的,因为软引用一般会在最后一次引用后保留几秒。
通过-XX:SoftRefLRUPolicyMSPerMB 参数设置,单位为ms。 最后,如果你想看JVM中引用和GC情况,可以使用一些工具,比如jdk8使用ParrallelGC 收集的垃圾收集日志,我们可以在启动命令中输入hotspot自带的运行参数查看:-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintReferenceGC 。但在jvm9中已经被重构,不再存在。 JAVA9中手动达到强引用的方式:
代码如下, class Resource {
private static ExternalResource[] externalResourceArray = …
int myIndex; Resource(…) {
myIndex = …
externalResourceArray[myIndex] = …;

}
protected void finalize() {
externalResourceArray[myIndex] = null;

}
public void action() {
try {
// 需要被保护的代码
int i = myIndex;
Resource.update(externalResourceArray[i]);
} finally {
// 调用 reachbilityFence,明确保障对象 strongly reachable
Reference.reachabilityFence(this);
}
}
private static void update(ExternalResource ext) {
ext.status = …;
}
}


原文链接:https://blog.csdn.net/u010867670/article/details/102019110

赞(0)
未经允许不得转载:91coding » JAVA基础:强引用、软引用、弱引用、幻象引用
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

立即登录   注册

91CODING 小白轻松上手,大牛稳健进步

关于我们免责声明