我知道在Java中我们有软引用的概念。如果:
1)软引用“sf”指对象A
2)在对象A中,它有一个强引用引用对象B
3)对象A& B不会在其他任何地方引用。
根据定义,对象A和对象B都“可以轻柔地到达”,对吗?
然后说我们现在用完了内存,GC开始了。有可能GC会回收对象B而不是对象A吗?
如果是这种情况,稍后如果我们想通过“sf”访问对象B,它将为null。 java如何避免这种情况发生?
我在java doc中没有看到任何解释。
答案 0 :(得分:6)
然后说我们现在用完了内存,GC开始了。有可能GC会回收对象B而不是对象A吗?
没有。 GC不会破坏可到达对象中的强引用。 (当然,作为回收过程的一部分,它会破坏无法到达的对象中的引用。但是你无法观察到这种情况......因为要观察它,你需要仍然可以访问该对象。)
这是java.lang.ref
包的javadoc中此语句的结果。
“最后,当一个对象无法访问,因此符合回收条件时,如果无法通过上述任何方式访问该对象。”
......其中“上述方式”包括强大,柔和,虚弱和虚幻的可达性。
这两个突出显示的词语意味着回收资格是处于无法到达状态的结果。由于其他州都没有提到填海资格,我们得出结论,不可达性是填海工程的先决条件。
这肯定与常识一致。如果(假设)允许GC在可到达对象中“清空”强引用,则应用程序在进入此状态后无法安全地处理对象。 (考虑这样一种情况,即引用的引用是在库类的实例中......)
答案 1 :(得分:2)
我认为简要介绍如何跟踪GCs基本上如何工作应该清理。
跟踪GC(Java和.NET中使用的那些都属于该类别)有一组所谓的root pointers
,这些是全局变量(在java中表示类的静态变量)并且全部是堆栈框架中的变量。 GC遍历这些并标记所有活动的对象,即通过至少一个根指针的引用可到达。完成后,所有实时变量都已标记,其余的可以被垃圾收集。
现在可以用两种不同的方式处理软引用:a)我们遵循软引用并标记其中的所有对象或b)我们不这样做。究竟发生了什么是由给定的JVM实现的摆布,但在此之后已经确定没有其他区别。
因此有两种可能的情况:
答案 2 :(得分:1)
来自文档:
“如果一个对象不能很容易到达,但可以通过遍历一个软引用来访问它。”
“如果一个线程可以在不遍历任何引用对象的情况下到达某个对象,则可以强烈访问该对象”
我认为这很清楚。 B可以轻柔到达,因为它只能通过遍历软引用来访问。