我正在为一个我一直在努力的游戏进行决斗系统,这里是这个类的骨架:
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时会发生什么。
答案 0 :(得分:8)
我应该如何正确地将类设置为由Java垃圾收集器收集。
您可能不需要做任何事情。如果没有来自其他地方的Duel
引用,那么Duel
对象本身就有资格进行垃圾收集......如果Duel
是引用相关Champion
的最后一件事。 {1}}对象(等)然后那些也有资格进行垃圾收集。
如果Champion
通过Duel
字段引用currentDuel
(听起来像是这样),那么如果你有一个单独的引用冠军(例如你有然后那些冠军将阻止Duel
被垃圾收集,直到currentDuel
被设置为不同的值。但实际上,你应该考虑逻辑上有用的东西,而不是担心垃圾收集...大概一旦决斗完成,将currentDuel
设置为null 无论如何是有意义的,因为冠军不再与那场决斗作斗争......而在这一点上,他们将不再让Duel
活着。你不太可能需要在Duel
中更改任何内容。
如果冠军本身有资格进行垃圾收集,那么您不必担心Duel
和Champion
之间的引用循环 - 这不会阻止垃圾收集。
所有这一切的原则是“我是否仍然可以通过任何实时线程的任何代码路径到达相关对象?”的问题。如果你不能,那么它将有资格进行垃圾收集。如果您可以到达相关对象,那么它将不会被垃圾收集。
答案 1 :(得分:5)
正如Jon Skeet所说,最好的办法是在你完成它之后引用你的对象超出范围。这不仅意味着您不需要将其设置为null
,而且您的应用程序将以更合理,更易于维护的方式构建。
您只需将对象图的顶部设置为null。一旦一个对象不再强烈可达,就可以清理它,并且可以清除任何指向不可强烈到达的对象。
在上面的情况中,最简单的事情可能是放弃Duel
对象本身,一切都可以清理。
如果您怀疑内存泄漏,可以使用内存分析器查看哪个引用保留在对象上。这告诉您哪个引用保留在对象上。在Java中,大部分内存泄漏是由于对象被添加到集合但未从集合中删除。