关于类实例的 Java 垃圾收集

标签 java garbage-collection

我对如何利用 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 类包含一个名为“visible”的 boolean 字段。当“visible”等于 false 时,处理我的 EnemyProjectile 类并使其符合垃圾回收条件的正确方法是什么?

最佳答案

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

在 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();

在此片段中,有几个问题:

当您使用 Java Collections API 中的数据结构时,您应该使用接口(interface)作为类型,而不是具体类。这是按照惯例,但这样做将使您的代码更加灵活。而不是...

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

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

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 程序,使您的对象能够尽早进行垃圾回收……然后就完全不用担心会发生什么。

关于关于类实例的 Java 垃圾收集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20157835/

相关文章:

java - ISO-8859-15 中的 Tomcat 无法写入带有拉丁字符的文件名

java - JPA @OneToMany 和@ManyToOne : back reference is null

node.js - node.js --trace-gc 输出的含义是什么?

c# - 如何在 C# 中尽早清除内存

java - 如何让Java类监听C程序 "stdout"上的事件

java - 返回文本中给定位置前后指定数量的单词

java - 垃圾收集器意外输出

java - java中的垃圾收集器方法有什么用?

scala - 尝试通过SBT构建项目时Docker中超出了GC开销限制

java - 分成 double 不起作用