[英]An object is still alive after I kill its holder in Java?
我一直在努力解決下一個錯誤。 我的程序結構如下
main
函數初始化一個Game
對象並調用startMainWindow()
,后者初始化一個GameLogic logic
對象和一個MainWindow
對象(將logic
作為參數以及this
傳遞給它)。 這兩個對象都是 startMainWindow()
中的局部變量 。
問題是,比如說當玩家完成游戲並且我想啟動高分GUI時,我會從MainWindow
調用_game.startHighScoreWindow()
。 問題在於GameLogic
對象一直在運行! 我通過在GameLogic.actionPerformed()
放置控制台寫入命令來輕松地對其進行檢查。 它不會從內存中釋放。 即使我調用this.dispose();
也會發生這種情況this.dispose();
在_game.startHighScoreWindow()
之前。
為什么_gameLogic
仍在內存中?
一些代碼:
PacmanGame:
public void startMainWindow(int levelIndex, int levelsDone, int score) {
gameGui = null; //desperate attempt
highScoreGui = null;
mainMenuGui = null;
spaceGui = null;
gameLogic = null;
System.gc();
gameLogic = new GameLogic(_sprites, _levels[levelIndex], levelsDone, score);
gameGui = new MainWindowGui(this, gameLogic, _sprites, _levels);
}
public void startHighscoreGui(int score, String time) {
gameGui = null;
highScoreGui = null;
mainMenuGui = null;
spaceGui = null;
gameLogic = null;
System.gc();
highScoreGui = new HighscoreGui(this, score, time);
}
主窗口:
public class MainWindow extends JFrame implements KeyListener {
private PacmanGame _game;
private GameLogic _gameLogic;
private GamePanel _gamePanel; //JPanel
private ToolbarPanel _toolbarPanel; //JPanel
private Sprite[] _sprites;
private Level[] _levels;
public MainWindow(PacmanGame game, GameLogic gameLogic, Sprite[] sprites, Level[] levels) {
// create our window
super("Pacman");
// initialize fields
_game = game;
_sprites = sprites;
_gameLogic = gameLogic;
_levels = levels;
this._gamePanel = new GamePanel(_gameLogic, _sprites);
this._toolbarPanel = new ToolbarPanel(_gameLogic, sprites, this);
...
}
public void playerWon(String time) {
Level levelObj = _gameLogic.getLevelObject();
int nextLevelIndex = (levelObj.getNum()) % 3;
if(_gameLogic.getLevel() == 3) //done!
{
this.dispose();
_game.startHighscoreGui(_gameLogic.getScore(), time);
}
else //next level
{
_gameLogic.nextLevel(_levels[nextLevelIndex]);
}
}
編輯:經過一次絕望的嘗試,我嘗試在PacmanGame中制作所有GUI和GameLogic靜態變量,然后每次在PacmanGame中調用函數時將它們設置為null。 它的行為與以前相同,也就是說,所有這些對象都位於每個函數的本地。
在回答您的問題時:
在用Java殺死對象的持有者后,該對象仍然存在嗎?
當對象變得不可訪問時,它就有資格刪除。 可到達意味着在尚未返回的某些方法的某些堆棧幀中,存在從static
或局部變量開始的對象路徑。
而且有些事情“有些特殊”,例如,線程運行時Thread
對象仍然可以訪問...而不管對Thread
的其他引用。 類似的情況適用於與GUI相關的對象。
為什么_gameLogic仍在內存中?
不看MCVE的代碼就無法分辨。 (您的UML圖和英語注釋沒有說……而且它們也不一定准確!)
查看您發布的摘錄,您的GameLogic
對象仍然可以訪問,因為在MainWindow
類的_gameLogic
字段中有_gameLogic
的引用。 而且MainWindow
對象仍然可以訪問,因為它已顯示。
但是正如我們所說,如果您想要正確的答案,則必須使用MCVE。 即,答案要比有根據的猜測更好。
這也值得注意/重復
System.gc()
是一個壞主意。 它很少起作用。 JFrame
類上調用dispose()
不會清除由類本身聲明的字段。 它不了解他們。 問題在於GameLogic對象一直在運行!
如果有東西繼續運行, 那么應該停止它。 這不是GC的工作。
它不會從內存中釋放。
同樣,立即發布所有內容或類似內容也不是GC的工作。 盡力而為的唯一工作就是不會耗盡內存。 它是通過收集垃圾來完成的,但這是一個實現細節。 它可以代替您購買新的RAM,也可以。
您的問題是使用了錯誤的工具來完成工作。
只要提供一個明確的方法來終止您的GameLogic
,就可以完成。 對於在循環中運行的線程,請使用volatile boolean stop
變量退出循環。 對於窗口,請使用dispose
等。
就這樣。 只是忘了有一個GC。 它不能幫助您了解游戲邏輯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.