首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在Java中,一个对象在我杀死它的持有者之后还活着吗?

在Java中,一个对象在我杀死它的持有者之后还活着吗?
EN

Stack Overflow用户
提问于 2018-06-05 06:27:08
回答 2查看 112关注 0票数 0

我为下一个bug苦苦挣扎了好几个小时。我的程序结构如下

main函数初始化一个Game对象并调用startMainWindow(),后者初始化一个GameLogic logic对象和一个MainWindow对象(将logic作为参数传递给它,还将this作为参数传递给它)。这两个对象都是 startMainWindow()中的局部变量。

问题是,假设玩家玩完游戏后,我想启动高分图形用户界面,我从MainWindow调用_game.startHighScoreWindow()。问题是GameLogic对象一直在运行!通过在GameLogic.actionPerformed()中输入控制台写命令,我可以轻松地检查它。它不会从内存中释放。即使我在_game.startHighScoreWindow()之前调用this.dispose();,也会发生这种情况。

为什么_gameLogic还在内存中?

下面是一些代码:

PacmanGame:

代码语言:javascript
复制
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);
    }

MainWindow:

代码语言:javascript
复制
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。它保持与以前一样的行为,也就是说,所有这些对象都是每个函数的本地对象。

EN

回答 2

Stack Overflow用户

发布于 2018-06-05 06:53:35

在回答您的问题时:

一个对象在我杀死它的持有者后仍然活着吗?

当一个对象变得不可访问时,它就有资格被删除。可到达的意思是,在某个方法的某个堆栈框架中,存在从static或局部变量开始的、尚未返回的对象的路径。

还有一些事情是“有点特殊”的,例如,Thread对象在线程运行时保持可达状态……而不考虑对Thread的其他引用。类似的事情也适用于与GUI相关的对象。

为什么_gameLogic还在内存中?

如果不看到MCVE的代码,就无法判断。(您的UML图和英语注释没有说...而且它们也不一定是准确的!)

查看您发布的代码片段,您的GameLogic对象仍然是可访问的,因为在MainWindow类的_gameLogic字段中有对它的引用。并且MainWindow对象仍然是可访问的,因为它被显示。

但正如我们所说的,如果你想要正确的答案,MCVE是必要的;即比有根据的猜测更好的答案。

这也值得注意/重复。

  • 调用System.gc()不是一个好主意。带下划线的works.
  • Prefixing变量很少不是标准的Java风格。(我称之为ugly.)
  • Windowing对象,如果它们当前正在显示,它们将不会被垃圾回收。有一些隐藏的引用(在SWT / AWT /JVM中)可以确保窗口对象在displayed.
  • Calling时是可访问的,扩展JFrame的类上的dispose()不会清理类本身声明的字段。它不知道他们的情况。
票数 3
EN

Stack Overflow用户

发布于 2018-06-05 20:41:57

问题是GameLogic对象一直在运行!

如果某个东西一直在运行,那么你就应该停止它。这不是GC的工作。

它不会从内存中释放。

同样,GC的工作不是立即发布所有内容或类似的内容。唯一的工作就是努力,你不会耗尽你的内存。它通过收集垃圾来做到这一点,但这是一个实现细节;它可以为您购买新的RAM,这样就没问题了。

你的问题是使用了错误的工具。

只需提供一个显式的方法来终止您的GameLogic,就完成了。对于在循环中运行的线程,使用volatile boolean stop变量退出循环。对于窗口,使用dispose等...

就这样。忘了有个GC吧。它不是用来帮助你理解游戏逻辑的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50689605

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档