垃圾多久收集一次?我认为我的对象没有被删除

Posted

技术标签:

【中文标题】垃圾多久收集一次?我认为我的对象没有被删除【英文标题】:How frequently is garbage collected? I don't think my objects are being deleted 【发布时间】:2012-08-13 00:32:22 【问题描述】:

如果我有一个类删除自己,它的内部方法是否应该停止执行?我有一个 B 类,它告诉 A 类从 A 的 ArrayList 中删除 B。我相当肯定 B 只存在于 A 的 ArrayList 中,所以当我删除它时,它应该被删除,对吗? (注意:我已经包含了一个 Serializable 实现,以防万一这与 VM 如何处理我的类有关,但我没有在这里写入 read- 和 writeObject 方法。我怀疑它与不过这个问题。)

public class A implements Serializable, B_Listener 
    ArrayList<B> bArray;

    public A() 
        bArray = new ArrayList<SomeObject>();
        bArray.add(new B(bArray.size(), this));
    

    @Override
    public void deleteAtIndex(int index) 
        bArray.remove(index);
    


public class B implements Serializable 
    B_Listener listener;
    int index;

    public B(B_Listener listener, int index) 
        this.listener = listener;
        this.index = index;
    

    //This is called at some point in a B's lifetime.
    private void selfDestruct() 
        listener.deleteAtIndex(index);
        Log.w("B.class", "Should this not output? It does.");
    


public interface B_Listener 
    public void deleteAtIndex(int index);

所以当我不相信它应该执行 Log.w 消息时。因此,恐怕我正在创建 java 的内存泄漏。我查看并查看了整个代码,试图找到 B 可能被指针保存的位置,但除了我想要的之外,我什么也没想到。

那么我问的是垃圾收集的时间是否与我最终删除 B 的时间不同。如果是这种情况,那么暂时可以肯定地说我实际上并没有持有我不打算持有的物品吗?

额外(注意:这可能很难理解,上面的所有内容都足以解决问题): 我也用 android-Views 标记了它,因为我正在 Android 上开发:我的 B 类包含指向 B 作为侦听器的 View 对象。我相信当我删除视图时,视图管理器或任何 Android 都不应再指向视图,当我删除 B 时,它的所有内部视图也应该被删除,这意味着它们不能再通过自己的侦听器来保持 B 的存在指针。我只是说出来看看我的理解是否正确。

【问题讨论】:

谁在打电话给B.selfDestruct() 你是在问为什么“selfDestruct”的第二行在第一行之后仍然执行? (为什么不应该?)FWIW 垃圾收集对您的应用程序应该是完全不可见的,并且根本不会干扰其行为。它所做的只是确保有足够的内存可用。不要试图与之互动。 B 有多个状态,因此如果 B 发现自己处于表明它无用的状态,它会调用 selfDestruct()。在我的实际代码中,没有 selfDestruct 方法,而是我构建的状态处理程序(在 B 内)只执行行 listener.deleteAtIndex(index)。我不想与垃圾收集进行交互。我试图理解它。我没有学过 Java,我学过 C++。 【参考方案1】:

当然不是。

只有在returns、抛出异常或线程被中止时,方法才会“停止执行”。

垃圾收集的全部意义在于它对您来说是不可见的。除非有特殊技巧(例如 WeakReferences 或检查空闲内存),否则无法判断一个对象是否已被垃圾回收 - 如果您可以检查它是否存在,则意味着您有对它的引用,所以它 无法收集

【讨论】:

特别是,this 无法在其方法之一仍在运行时进行垃圾收集。至少,调用当前方法的对象仍然有对该对象的引用(在方法调用完成并且堆栈展开后,该引用可能会消失,但之前不会)。 谢谢你们!这是我需要听到的。我曾认为垃圾收集是即时的。不幸的是,由于我是新人,所以我不能赞成您的回答:( 我只想指出,SLaks 正在回答我在这篇文章正文中提出的问题,供以后阅读本文的人使用。 顺便说一句,一个对象何时有资格被 GC 和它实际被收集是有区别的。 GC 通常不会收集对象,直到它需要——也就是说,直到它用完空间(我在这里画了一点粗刷)。这让它可以批量 GC,速度更快(以使用更多 RAM 为代价)。【参考方案2】:

    通常会有两种 GC:次要(每秒左右)和主要(每隔一小时左右,但如果您为 VM 提供足够的内存,也可能是一周)。

    对象以异步方式释放(批量执行此操作更有效,并且有助于保持内存不碎片化)。它们在不可访问的毫秒内不会被删除。

    垃圾收集只有在没有活动的线程 能够访问对象时才有意义,而不是在没有对象 持有对它的引用时才有意义。在您的代码中,只要 selfDestruct 运行,线程就拥有一个隐式的“this”引用。这实际上会导致对象被线程引用 - 并且不受 GC 影响。

【讨论】:

谢谢,这强化了上面的答案,加深了我对 GC 的理解。

以上是关于垃圾多久收集一次?我认为我的对象没有被删除的主要内容,如果未能解决你的问题,请参考以下文章

为啥在执行 Java Stream 终端操作时对象没有被垃圾收集?

-垃圾收集器内存分配策略

垃圾收集器与内存分配策略---垃圾收集算法

内联创建和使用一次性对象是不是安全?

jvm-3学习教程

java有自动垃圾回收机制