Java 如果存在两级软引用对象,GC将做什么

Java 如果存在两级软引用对象,GC将做什么,java,garbage-collection,soft-references,Java,Garbage Collection,Soft References,我知道在Java中我们有软引用的概念。如果: 1) 有一个软引用“sf”引用对象a 2) 在对象A中,它有一个指向对象B的强引用 3) 对象A和B不在其他任何地方引用 根据定义,对象A和对象B都是“软可达的”,对吗 然后假设我们现在内存不足,GC启动。GC是否可能回收对象B而不是对象A 如果是这样的话,稍后如果我们想通过“sf”访问对象B,它将是空的。java如何避免这种情况发生 我在java文档中没有看到任何解释 然后假设我们现在内存不足,GC启动。GC是否可能回收对象B而不是对象A 否。GC

我知道在Java中我们有软引用的概念。如果:

1) 有一个软引用“sf”引用对象a

2) 在对象A中,它有一个指向对象B的强引用

3) 对象A和B不在其他任何地方引用

根据定义,对象A和对象B都是“软可达的”,对吗

然后假设我们现在内存不足,GC启动。GC是否可能回收对象B而不是对象A

如果是这样的话,稍后如果我们想通过“sf”访问对象B,它将是空的。java如何避免这种情况发生

我在java文档中没有看到任何解释

然后假设我们现在内存不足,GC启动。GC是否可能回收对象B而不是对象A

否。GC不会中断可访问对象中的强引用。(当然,作为回收过程的一部分,它会中断无法访问对象中的引用。但您无法观察到这种情况……因为要观察它,您需要对象仍然可以访问。)

这是javadoc中针对
java.lang.ref
包的这条语句的结果

“最后,对象是不可访问的,因此,在无法通过上述任何一种方式访问对象时,有资格回收。”

。。。其中“上述方式”包括强可达性、软可达性、弱可达性和虚可达性

突出显示的两个词意味着填海资格是处于无法到达状态的结果。由于没有其他州提到填海资格,我们得出结论,不可达性是填海的先决条件

这当然符合常识。如果(假设)允许GC“清空”可访问对象中的强引用,应用程序就不可能在对象进入这种状态后安全地处理它们。(考虑取消的引用位于库类实例中的情况…

来自文档:

“如果对象不是强可达对象,但可以通过遍历软引用来访问,则该对象是软可达对象。”

“如果某个线程无需遍历任何引用对象即可访问某个对象,则该对象是强可访问的”

我想这很清楚。B是软可及的,因为它只能通过遍历软引用来达到


我认为,简单介绍一下跟踪地面军事系统的基本工作原理应该会让事情变得更清楚

跟踪GC(Java和.NET中使用的都属于这一类)有一组所谓的
根指针
,它们是全局变量(在Java中表示类的静态变量)和堆栈框架中的所有活动变量。GC遍历这些对象并标记所有活动的对象,即通过至少一个根指针的引用可以访问的对象。完成后,所有活动变量都已标记,其余变量可以进行垃圾收集

现在可以用两种不同的方式处理软引用:A)我们遵循软引用并标记其中的所有对象,或b)我们不这样做。到底发生了什么取决于给定的JVM实现,但在确定之后,就没有其他区别了

因此,有两种可能的情况:

  • GC遵循对A的软引用,在这种情况下,两个对象都不会被GCD
  • GC不遵循对A的软引用(也没有硬引用)。A是GCed,如果没有活动对象引用它,B是GCed

我认为GC要么收集A和B,要么两者都不收集,因为这是合乎逻辑的,但这只是猜测。你有没有说明这一点的来源?@Jeffrey:这会完全破坏语言语义。如果任何外部块使用WeakReference,则程序任何部分中的任何引用都可能在任何时候由于任何明显的原因而任意变为null。那太可怕了@StevenSchlansker它不会影响我程序任何部分中的任何引用,只影响软可及或弱可及的引用。@Jeffrey软可及对象是GCed还是非GCed。想象一下,如果你突然有了部分GCed,但仍然可以到达的对象,那么会有多么混乱。来自
if(foo!=null)foo.bar()等事物的NPE会让人很困惑,不是吗?”斯蒂芬补充了一个关于GCing对象a的小附录。这很明显,但我认为在这里明确说明不会有什么坏处。如果你不喜欢,我知道。但我想知道我第二个更重要问题的答案。嗯,不要使用软引用。将对B的引用存储在强引用缓存中。一张支票将被收取。因为图形是向下遍历的。没有什么能阻止你收集,因为我并没有试图解决这个问题。我试图理解GC worksGC是如何实现可访问性的。在您的场景中,A和B都符合GC的条件,因为根据定义,它们是软可访问的。如果将对B的强引用存储在其他位置,它将成为强可访问的,但a仍然是软可访问的,并且符合GC的条件。请记住,java规范仅根据它所能产生的gaurantees来定义内容。您需要参考特定的实现,以了解实际算法的更多细节。查看Glassfish和OpenJDK参考实现它有很多关于hotspot如何做事情的有用信息。顺便说一句,唯一真正的GC根是JNI参考,其余的对象(应该)符合GC条件(这就是为什么ClassLoader有一个
向量类
)@bestsss你说得对,但我认为忽略所有丑陋的细节,简化了基本的理解。我只是希望没有人会问,如果静态变量真的是根指针,Hotspot如何卸载类;)我认为忽略所有丑陋的细节,简化了基本的理解-完全同意,同时