Callback的游戏崩溃失败,因为闭包实例已被垃圾收集

时间:2015-11-10 20:09:19

标签: java crash fullscreen lwjgl glfw

我的小游戏有问题。我是LJWGL3中的新手(很长一段时间使用过2),并希望实现一个Key来在窗口和全屏模式之间切换。我已经可以做到这一点没有大问题。但是如果我经常按下这个键,我的游戏就会崩溃。有时晚或早。没有定时崩溃。我尝试了很多(3个小时),现在已经没有想法了。谁知道我做错了什么?我无法发布完整的源代码,因为它很多。 我在这里发布一些重要的代码部分。 首先是错误:

    if(glfwGetKey(appID, GLFW_KEY_F) == GLFW_PRESS) {
        FullscreenCreation.setFullScreen(!fullscreen);
    } 

这是我用来检查KEY是否下载的代码:

    public static void setFullScreen(boolean fullScreen) {

    //i don't have copy the variables like fullscreen to here
    if (fullscreen == fullScreen)
        return;
    fullscreen = fullScreen; 

    if (fullScreen) {
        windowWIDTH = WIDTH;
        windowHEIGHT = HEIGHT;

        //get monitor resolution
        ByteBuffer vidMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
        WIDTH = GLFWvidmode.width(vidMode);
        HEIGHT = GLFWvidmode.height(vidMode);
    } else {
        WIDTH = windowWIDTH;
        HEIGHT = windowHEIGHT;
    }       

    //create new window THIS IS THE POINT WHERE ITS CRASH AFTER A WHILE
    long display = glfwCreateWindow(WIDTH, HEIGHT, MainAction.BASIC_WINDOW_TITLE, fullScreen ? glfwGetPrimaryMonitor() : 0, appID);
    glfwDestroyWindow(appID); //kill the window (for now)

    //add new callback for resizing the window
    glfwSetCallback(display, GLFWWindowSizeCallback(new SAM() {
        @Override
        public void invoke(long window, int width, int height) {
            if(width!=0 && height!=0) {
            WIDTH=width;
            HEIGHT=height;
            isResize=true;
            }
        }
    }));


    //now apply the new fullscreen window
    appID = display;

    //some GL stuff for the new window
    glfwMakeContextCurrent(appID);        
    GL.createCapabilities();

    glfwSwapInterval(0); //disable vsync

    //only call glEnable(GL_TEXTURE_2D), GL_BLEND ...
    DisplayCreation.enableGLStuff();

    isResize = true;
}

这是我的FullscreenCreation.java

{{1}}

如果您需要更多代码,我会发布更多代码。

1 个答案:

答案 0 :(得分:0)

您需要对您创建的每个回调保留一个强引用,因为垃圾收集器不知道它在本机代码中使用,因此会收集它。

所以这意味着你必须将回调对象存储在一个字段中。

private static GLFWWindowSizeCallback sizeCallback;

//...

public static void setFullScreen(boolean fullScreen) {
    //...
    sizeCallback = GLFWWindowSizeCallback(new SAM() {
        //...
    };
    glfwSetCallback(display, sizeCallback);
    //...
}

然后,当你完成使用回调时(即当你破坏窗口时),你只需要释放它。

sizeCallback.release();

注意:要释放给定窗口的所有回调,您还可以使用Callbacks.glfwReleaseCallbacks

对于LWJGL 2和3之间的差异,您可以查看migration guide,其中还包含此问题的简要说明。