如果主引用指向null,WeakReference或SoftReference有什么不同?
如果主引用指向null,WeakReference或SoftReference有什么不同?
我在阅读关于WeakReference
和SoftReference
的内容。
发现以下内容:
WeakReference:
Counter counter = new Counter(); // strong reference - line 1 WeakReference weakCounter = new WeakReference(counter); //weak reference counter = null; // now Counter object is eligible for garbage collection
Soft Reference:
Counter prime = new Counter(); // prime holds a strong reference - line 2 SoftReference soft = new SoftReference(prime) ; //soft reference variable has SoftReference to Counter Object created at line 2 prime = null; // now Counter object is eligible for garbage collection but only be collected when JVM absolutely needs memory
这里,无论如何我都会将counter和prime的强引用赋值为null,它们将会被垃圾回收器回收,等到下一轮GC周期运行时。
WeakReference
/ SoftReference
在这里如何影响/协助垃圾回收?
更新:
在下面的程序中:
public class WeakReferenceSample { public static void main(String[] args) { HelloWorld helloWorld = new HelloWorld(); WeakReference helloWorldReference = new WeakReference<>(helloWorld); helloWorld = null; System.out.println(helloWorld); System.out.println(helloWorldReference.get()); System.gc(); System.out.println(helloWorldReference.get()); } }
即使将helloWorld
引用更改为null
,我的第一个System.out.println(helloWorldReference.get());
仍然打印出对象的值而不是null
。在System.gc()
之后,第二次它打印出了null
。当helloWorld
引用和helloWorldReference
引用都指向同一个HelloWorld
对象时,这是如何在内部工作的。
示例输出:
null HelloWorld@2503dbd3 null
证明:如果我不将null
分配给helloWorld
引用,那么helloWorld
引用和helloWorldReference
引用都将指向同一个HelloWorld
对象。
HelloWorld@2503dbd3 HelloWorld@2503dbd3 HelloWorld@2503dbd3
对其内部运作方式感到困惑吗?之前我一直认为它会克隆对象,然后使用弱引用,但从输出结果来看貌似不是这样。
长话短说
没有一个对象有强引用,因此对象有资格进行垃圾收集。但是不同的引用类型将确定垃圾收集器如何优先处理对象的垃圾收集。
垃圾收集周期期间发生的实际详细信息可以因不同参数而异。以下是其中一些参数:
- JRE/VM版本
- 所选的实际垃圾收集算法
- 系统中可用的内存
- 系统资源
从原则上讲,垃圾收集器尝试在不影响长期和短期性能的情况下快速有效,并同时确保有足够的可用内存。
因此,在垃圾收集期间,垃圾收集器将尝试通过回收某些对象来释放一些内存。垃圾收集器最终将确定将释放多少内存以及要垃圾收集哪些对象来执行此操作。垃圾收集器不一定在每次运行时垃圾收集所有具有资格的对象。
因此,我们可以说有资格进行垃圾收集的对象将以不同的优先级进行垃圾收集。因此,垃圾收集优先级如下:
- 没有引用的对象具有最高的垃圾收集优先级。
- 弱引用对象是下一个更有资格进行垃圾收集的对象。
- 软引用对象是下一个更有资格进行垃圾收集的对象。
基于这种优先级设置,弱引用的对象可能比软引用的对象更容易被垃圾收集。但是,何时垃圾收集每个对象的决定和责任仅由垃圾收集器负责。
定义涉及优先级(渴望程度)而不是精确规则,因此可以期望观察到:
从长远来看(如果在许多不同的JRE和不同的情况下观察),弱引用对象往往比软引用对象更容易被垃圾收集。
“软引用与弱引用完全相同,只是它不那么渴望丢弃它所引用的对象。”引用自此答案;软引用和弱引用Java还包括幻象引用,这是一个相关的概念。幻象引用
根据问题的更新进行更新:
在您的第一个示例中:
null
这是预期的,因为它是显式设置为null的helloWorld变量中的强引用。
HelloWorld@2503dbd3
弱引用在helloWorldReference变量中还没有被垃圾回收,因此它仍然存在。但是由于这是该对象的唯一引用,所以它有资格进行垃圾回收。如果您多次运行此示例,则可能会发生将其打印为null的情况。如果您运行消耗太多内存的另一个线程,您可以看到它。
null
在helloWorldReference变量中的弱引用已被垃圾回收。具体取决于正在运行的垃圾收集器,这个对象也可能不是null。 垃圾收集器除了取决于VM和VM启动前给出的参数之外,还可以看其他文档,如System.gc javadoc中所述。
调用gc方法建议 Java虚拟机花费一些费用来回收未使用的对象,以便使它们当前占用的内存可用于快速重用。当方法调用返回控件时,Java虚拟机已尽最大努力从所有丢弃的对象中回收空间。
注意粗体字。它们暗示这种方法并不总是有相同的结果。调用这个方法是对VM的建议,它将以最佳努力的基础行动。
在您的第二个例子中:
HelloWorld@2503dbd3
在helloWorld变量中存在强引用
HelloWorld@2503dbd3
在helloWorldReference变量中的弱引用尚未被垃圾回收,因为此对象已经有一个强引用。该对象不可进行垃圾回收。
HelloWorld@2503dbd3
在helloWorldReference变量中的弱引用检索该对象,因为它还没有被垃圾回收。由于该对象已经有一个强引用,所以该对象永远不会被垃圾回收。