应用程序关闭后,JOGL javaw.exe仍在运行

时间:2012-09-29 13:01:19

标签: java opengl jogl

我有一个使用JOGL的简单java应用程序。当我从eclipse运行它,然后关闭应用程序窗口时,javaw.exe仍然在运行。以下是相关代码:

public class App {
    private Display mDisplay;
    private Shell mShell;
    private GL4 mGl;
    private int mProgramId;
    private int mVsId;
    private int mFsId;

    // ...

    public void start() {
        if (!initialize()) {
            return;
        }

        while (!mShell.isDisposed()) {
            if (!mDisplay.readAndDispatch()) {
                mDisplay.sleep();
            }
        }

        destroy();
    }

    private void initialize() {
        mDisplay = new Display();
        mShell = new Shell(mDisplay);

        // some SWT and opengl initialization code, which is irrelevant for this issue
        // (at least I think so)
        // getting GLProfile, GLContext, GL4 etc.

        final String vsText = ResourceManager.getShaderText(vsPath);
        final String fsText = ResourceManager.getShaderText(fsPath);

        mVsId = mGl.glCreateShader(GL4.GL_VERTEX_SHADER);
        mFsId = mGl.glCreateShader(GL4.GL_FRAGMENT_SHADER);

        mGl.glShaderSource(mVsId, 1, new String[] { vsText }, null, 0);
        mGl.glCompileShader(mVsId);

        mGl.glShaderSource(mFsId, 1, new String[] { fsText }, null, 0);
        mGl.glCompileShader(mFsId);

        mProgramId = mGl.glCreateProgram();

        mGl.glAttachShader(mProgramId, mFsId);
        mGl.glAttachShader(mProgramId, mVsId);

        // bind a constant attribute location for positions of vertices
        mGl.glBindAttribLocation(mProgramId, 0, "in_Position");
        // bind another constant attribute location, this time for color
        mGl.glBindAttribLocation(mProgramId, 1, "in_Color");
        mGl.glLinkProgram(mProgramId);

        // here error code is 0x0 (no error)
        int error = mGl.glGetError();

        mShell.open();

        return true;
    }

    private void destroy() {

        // here error code is 0x502 (GL_INVALID_OPERATION)
        int error = mGl.glGetError();

        mGl.glDetachShader(mProgramId, mFsId);
        mGl.glDetachShader(mProgramId, mVsId);

        mGl.glDeleteShader(mFsId);
        mGl.glDeleteShader(mVsId);
        mGl.glDeleteProgram(mProgramId);

        mDisplay.dispose();
    }
}

我注释掉了所有渲染代码和大多数其他与opengl / JOGL相关的调用(除了获取GLProfile,GLContext,GL4以及此示例中列出的所有内容),此问题仍然存在。

通常,应用程序工作正常,着色器编译和链接没有问题(我使用了验证,我没有在此示例中显示),它显示它需要什么。唯一的问题是javaw.exe在关闭应用程序窗口后仍然运行(通过按窗口一角的x)。

仅当我评论mGl.glCompileShader(mVsId);及后续行时,才会删除此问题。如果我离开这一行,javaw.exe将继续运行,所以我猜这个问题与着色器初始化/破坏代码有关。

此外,glGetError()在destroy()的末尾返回0(无错误),在destroy()的开头返回0x502(GL_INVALID_OPERATION)。中间只有主循环,没有我知道的opengl调用,因为为了测试,我注释掉了所有渲染代码。

有什么想法吗?

修改2012-10-03:

我仍然不知道问题是什么,但是自从我更新了我的显卡驱动程序后,“javaw.exe”会在应用程序关闭后终止。我有AMD Radeon HD 6870.我目前的驱动版本是2012年7月27日的8.982,我不记得最后一个版本是什么,但我相信它是从2011年1月左右开始的。

然而,glGetError()在destroy的开头仍然返回0x502,所以我猜还是有问题。

2 个答案:

答案 0 :(得分:1)

假设您使用jogamp.org中的JOGL,请使用我们的SWT GLCanvas 或我们的NEWTCanvasSWT。 由于自定义GLCapabilities,后者是首选,请检查API文档。 这个给出加上你在SWT线程上做的所有SWT相关(阅读 链接单元测试),恕我直言它应该工作 - 至少我们的单元测试。

由于您在更新(GPU /驱动程序)后提到您的麻烦不复存在, 这可能是一个司机问题。

现在你的GL错误了。可以通过设置系统属性'jogl.debug.DebugGL',即在命令行“-Djogl.debug.DebugGL”上简单地完成跟踪GL错误。 这将自动为GL对象安装调试管道,并检查GL错误,如果出现则会抛出GLException。

您还可以通过属性'jogl.debug.TraceGL'进行追踪。

答案 1 :(得分:0)

我不知道这是否相关,但可能会帮助我猜到的人,所以我将在这里分享。请记住,我只是Java SWT的业余爱好者。

我使用Java SWT库在Eclipse IDE中创建了一个简单的应用程序。我在主Window外壳中做了一个“退出”按钮,按下该按钮时会调用此按钮:

    quitBtn.addSelectionListener(new SelectionAdapter() {
        @Override
        public void widgetSelected(SelectionEvent e) {
            shell.getDisplay().dispose();
            System.exit(0);
        }
    });

将.jar文件导出到桌面后,我使用LaunchJ4包装器将其转换为.exe文件,并使用singleR3XPlayer互斥锁在“单实例”选项卡中选中“仅允许应用程序的单个实例”。

当我使用“退出”按钮关闭.exe文件时,一切都很好,并且javaw.exe会终止。但是,当我使用右上角窗口中的X按钮关闭外壳程序时,javaw.exe将保持运行状态。我发现当我尝试删除.exe文件(Windows“已使用的文件,仍在Java(TM)Platform SE二进制文件中打开,关闭该文件并重试”错误弹出窗口)时,发现无法打开使用X按钮关闭文件后,该文件的另一个实例(由于单实例互斥锁)。另外,如果我执行几个.jar文件(即使在关闭它们之后,也只能使用X而不是“ Quit”按钮),则将继续运行javaw.exe的多个实例。

我发现用X按钮关闭窗口只会丢弃外壳而不会退出程序。但是按下“退出”按钮将因为它调用了System.exit(0)。所以我做到了:

    // SWT Event Loop
    while (!shell.isDisposed()) {
        if (!display.readAndDispatch()) 
            display.sleep();
    }

    // To make sure javaw.exe terminates when Window is closed
    if (shell.isDisposed()) {
        System.exit(0);
    }

因此,在完成SWT事件循环(shell.isDisposed()== true)之后,我确保将调用System.exit(0)。这样,javaw.exe都会终止。

我不知道SWT的工作方式,也不知道这是否是正确的方法,但是它确保一旦应用程序关闭,javaw.exe就会终止。

希望有帮助。