【问题标题】:Java Garbage Collection regarding class instances关于类实例的 Java 垃圾收集
【发布时间】:2013-11-23 02:36:57
【问题描述】:

对于如何利用 Java 的垃圾收集来处理不再使用的对象实例,我有点困惑。我有几个问题:

在我的游戏中,我生成了大炮而不将它们存储在如下变量中:

        new Cannon("down", tileX, tileY, 65);

这个对象是否总是有资格进行垃圾回收?如果是,那么它什么时候会真正被处理掉?

==

对于我的 Cannon 类,我在创建时将所有实例添加到静态数组列表中。这是我第一次尝试使用垃圾回收:

    ArrayList<Cannon> cannonList = Cannon.getCannons();
    for (int i = 0; i < cannonList.size(); i++) {
        Cannon c = (Cannon) cannonList.get(i);
        c = null;
    }
    for (int i = 0; i < cannonList.size(); i++) {
        cannonList.remove(i);
    }
   System.gc();

当我设置“c = null;”时,它是否使原始 Cannon 为“null”,从而使其有资格进行垃圾收集,或者它是否对对象进行新的引用 c,然后将其设置为 null,让它对我没有任何作用?

==

我的 Cannon 类不断创建 EnemyProjectile 类的实例。 EnemyProjectiles 类包含一个名为“可见”的布尔字段。当“可见”等于 false 时,处置我的 EnemyProjectile 类并使其符合垃圾收集条件的正确方法是什么?

【问题讨论】:

  • 一个对象在不再有任何引用后被回收一段时间。基本方案是“标记和扫描”,其中程序首先“遍历”对象 A 指向对象 B 指向对象 C 的整个“树”……,“标记”每个到达的对象。然后检查所有对象,并回收那些未标记为可达的对象。
  • “它是否对对象创建一个新的引用 c,然后将其设置为 null,让它对我什么都不做?” 是的,它对你没有任何作用。从列表中删除一个项目并且(可能)不再引用它是使其符合 GC 条件的原因。

标签: java garbage-collection


【解决方案1】:

使用 Java 的乐趣在于,内存是在后台为您管理的,因此,与 C 或 C++ 不同,您不必担心对象的解构或处置。当一个对象不再“可用”(定义为超出范围并且无法从另一个活动对象访问)时,垃圾收集器会悄悄地回收它所占用的空间。

在 Java 中,您无法控制对象何时被垃圾回收,也不应该尝试。

依赖于未使用对象的确定性垃圾收集的代码总是脆弱且难以在 Java 中维护。部分原因是不同的 JVM 实现会在不同的时间进行垃圾收集。 System.gc(); 充其量只是向 JVM 建议它进行垃圾收集,但不能保证它何时(或什至)会发生。

您能做的最好的事情是设计您的程序,以使引用变量具有绝对最短的生命周期。每当长寿命对象保留对短寿命对象的引用(例如侦听器)或创建自己“管理内存”的数据结构(例如,您自己的队列或堆栈)时,您的代码就有内存泄漏的风险实施)。

ArrayList<Cannon> cannonList = Cannon.getCannons();
for (int i = 0; i < cannonList.size(); i++) {
    Cannon c = (Cannon) cannonList.get(i);
    c = null;
}
for (int i = 0; i < cannonList.size(); i++) {
    cannonList.remove(i);
}
System.gc();

在这个sn-p中,有几个问题:

当您使用 Java Collections API 中的数据结构时,您应该使用接口作为类型,而不是具体的类。这是约定俗成的,但这样做会使您的代码更加灵活。而不是...

ArrayList<Cannon> cannonList = Cannon.getCannons();

改为这样写(对任何实现 List 接口的类实例都有效):

List<Cannon> cannonList = Cannon.getCannons();

如果可能,您应该使用 Java SE 5 中引入的增强的 for-each 循环。它不易出错。您的 for 循环应如下所示:

for (Cannon c : cannonList) {
    c = null;  // this for loop actually accomplishes no useful work since
               // the reference is null'd as soon as it gets a reference to
               // a Cannon object.  The reference in your ArrayList is unaffected
               // by this assignment
}

cannonList.clear();  // more concise than removing each element from the list.

TL;DR:垃圾收集在发生时发生。它是非确定性的。您永远无法保证何时甚至是否会发生。设计您的 Java 程序,以使您的对象尽早符合垃圾收集的条件......然后完全不用担心会发生什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-13
    • 1970-01-01
    • 1970-01-01
    • 2013-04-20
    • 1970-01-01
    • 2010-12-13
    • 2016-08-16
    • 2013-03-09
    相关资源
    最近更新 更多