有没有办法接收对象,而没有参考它?

时间:2016-02-08 09:47:47

标签: java garbage-collection jvm

假设以下代码:

Object obj = new Object();
obj = null;

此时,我没有对此对象的任何引用,但它仍然在堆上,因为垃圾收集不会立即发生。在GC收集之前,有没有办法重新获得此对象的参考?

到目前为止,我看到的唯一可能的方法是使用Unsafe,它提供直接内存访问,但我需要知道内存在哪里准确分配了对象。此外,还有Weak \ SoftReference,但它们是通过特殊的GC行为实现的。

P.S。预测类似的问题"为什么需要它?" - 因为科学不是为什么,而是为什么不呢! (c)中

2 个答案:

答案 0 :(得分:2)

这是高度JVM实现特定的。在一个具有与每个对象关联的内存分配信息的简单实现中,您可以找到一个尚未释放内存的对象,而您似乎正在考虑这个方向。

但是,复杂的JVM不能以这种方式工作。考虑到运行时可能有数百万个对象,将分配信息与每个对象相关联会产生巨大的开销。不仅关于内存要求,还关于在分配或释放对象时维护这些信息所必须完成的工作量。

那么是什么让你的堆内存的一部分成为对象?只有您持有的参考。垃圾收集器遍历现有引用,并且在以这种方式找到的对象内,它将找到理解有多少内存属于该对象以及如何解释所包含数据(遍历该子对象)所需的元信息(即指向类特定信息的指针)。 -references,如果有的话)。未引用的所有内容本身都是未使用的,可能包含旧对象,或者根本就没有使用过,谁知道。一旦对对象的所有引用都消失了,就没有关于此对象以前存在的信息。

说到这一点,没有明确的自由行动。当垃圾收集器找到幸存的对象时,它们将被复制到一个专用的新位置,并且它们的旧位置被认为是空闲的,无论之前有多少个对象,每个对象有多少内存在它活着的时候占据了。

当您搜索被认为未使用的内存时,您可能会发现旧对象的回忆,但是如果没有引用它们的起点,则无法确定看起来像对象的位模式是否真的是死对象或只是巧合。即使你设法以某种方式复活了一个对象,它也与你最初能够复活引用的想法无关,因为gc还没有运行。

请注意,对此普通生命周期的所有修改都通过保持对该对象的另一个引用来工作。例如,当类定义了一个非平凡的finalize()方法时,JVM必须添加对需要完成的对象队列的引用。类似地,soft,weak和phantom references封装了对相关对象的引用。调试器一旦看到它就可以保持对对象的引用。

但是对于你的简单代码Object obj = new Object(); obj = null;,假设中间没有设置断点,则不会有额外的引用,因此无法恢复对象。在运行时优化代码时,JVM甚至可能会忽略整个分配。因此,在搜索时,您甚至不会在RAM中找到对象的剩余部分,因为该对象实际上从未存在过。

答案 1 :(得分:-1)

  

此时,我没有任何对此对象的引用,但它仍然在堆上,因为垃圾收集不会立即发生。

它未定义在何处,并且未定义垃圾收集是否立即发生。

  

在GC收集此对象之前,有没有办法重新获取此对象的参考?

你已经有了一个,然后扔掉了。保持它。

  

我需要知道在内存中确切分配对象的位置。

标准Java中没有任何内容可以告诉您这一点,如果您能够获得信息,则没有任何有用的方法可以利用这些信息。

  

此外,还有Weak/SoftReference,,但它们是通过特殊的GC行为实现的。

我不知道这会如何影响你的问题,无论它是什么。