如何正确准备垃圾收集类?

时间:2014-11-16 08:36:01

标签: java garbage-collection

我正在为一个我一直在努力的游戏进行决斗系统,这里是这个类的骨架:

public class Duel {

    private Champion challenger;
    private Champion defendant;

    private boolean duelStarted;

    private long timer;

    public Duel(Champion challenger, Champion defendant) {..

    public void tick() {..

    public void declineDuel() {..

    public void endDuel(ResultType resultType, Champion winner, Champion forfeit) {..

    public void declareWinner(Champion player) {..

    public void declareForfeit(Champion player) {..

    private enum ResultType {..

    public Champion getChallenger() {..

    public Champion getDefendant() {..
}

本课程将分配给挑战者和被告的冠军班级。

当决斗结束时(通过调用Duel#declineDuel()Duel#endDuel(ResultType, Champion, Champion)或由Champion#Disconnect()之类的东西有效),我应该如何正确设置类以便由Java垃圾收集器收集

我从来没有完全理解这一点,我是否需要将类中的所有内容设置为null,以及Duel currentDuel;中的Champion.class声明,或者我应该只设置当前的启动等于null,这将有效地停止引用(我认为,这是我对此感到困惑的)这个类的实例。

我不太明白垃圾收集会考虑什么"参考"如果被Duel#getChallenger()设置,它会被认为是被引用的,即使它没有被外部类触及?

我想我在入境和出境参考之间感到困惑,是否有人愿意摆脱一些启示,因为我似乎无法理解当我rtfm时会发生什么。

2 个答案:

答案 0 :(得分:8)

  

我应该如何正确地将类设置为由Java垃圾收集器收集。

您可能不需要做任何事情。如果没有来自其他地方的Duel引用,那么Duel对象本身就有资格进行垃圾收集......如果Duel是引用相关Champion的最后一件事。 {1}}对象(等)然后那些也有资格进行垃圾收集。

如果Champion通过Duel字段引用currentDuel(听起来像是这样),那么如果你有一个单独的引用冠军(例如你有然后那些冠军将阻止Duel被垃圾收集,直到currentDuel被设置为不同的值。但实际上,你应该考虑逻辑上有用的东西,而不是担心垃圾收集...大概一旦决斗完成,将currentDuel设置为null 无论如何是有意义的,因为冠军不再与那场决斗作斗争......而在这一点上,他们将不再让Duel活着。你不太可能需要在Duel中更改任何内容。

如果冠军本身有资格进行垃圾收集,那么您不必担心DuelChampion之间的引用循环 - 这不会阻止垃圾收集。

所有这一切的原则是“我是否仍然可以通过任何实时线程的任何代码路径到达相关对象?”的问题。如果你不能,那么它将有资格进行垃圾收集。如果您可以到达相关对象,那么它将不会被垃圾收集。

答案 1 :(得分:5)

正如Jon Skeet所说,最好的办法是在你完成它之后引用你的对象超出范围。这不仅意味着您不需要将其设置为null,而且您的应用程序将以更合理,更易于维护的方式构建。


您只需将对象图的顶部设置为null。一旦一个对象不再强烈可达,就可以清理它,并且可以清除任何指向不可强烈到达的对象。

在上面的情况中,最简单的事情可能是放弃Duel对象本身,一切都可以清理。

如果您怀疑内存泄漏,可以使用内存分析器查看哪个引用保留在对象上。这告诉您哪个引用保留在对象上。在Java中,大部分内存泄漏是由于对象被添加到集合但未从集合中删除。