1

我有一个使用 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() 在 initialize() 结束时返回 0(无错误),在 destroy() 开始时返回 0x502 (GL_INVALID_OPERATION)。中间只有主循环,没有我知道的 opengl 调用,因为为了测试,我注释掉了所有渲染代码。

有任何想法吗?

编辑 2012-10-03:

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

但是,glGetError()在destroy开始的时候还是返回0x502,所以我猜还是有问题。

4

2 回答 2

1

Assuming you use JOGL from jogamp.org, pls use either our SWT GLCanvas or our NEWTCanvasSWT. The latter is preferred due to custom GLCapabilities, pls check API doc. This given plus you are doing everything SWT related on the SWT thread (read linked unit tests), IMHO it should work - at least our unit tests.

Since you mentioned after an update (GPU/driver) your troubles ceased to exist, it might have been a driver problem.

Now to your GL error. Trace GL errors can be simply done by setting the system property 'jogl.debug.DebugGL', i.e. on the commandline "-Djogl.debug.DebugGL". This will install the debug pipeline for your GL object automatically and checks for GL error, which will throw an GLException if appear.

You can also trace via the property 'jogl.debug.TraceGL'.

于 2012-10-07T01:15:51.070 回答
0

我不知道这是否相关,但可能会帮助我猜想的人,所以我会在这里分享。请记住,我只是一个开始使用 Java SWT 的爱好者。

我使用 Java SWT 库在 Eclipse IDE 中创建了一个简单的应用程序。我在我的主窗口外壳中制作了一个“退出”按钮,当按下它时会调用它:

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

将 .jar 文件导出到 Desktop 后,我使用 LaunchJ4 包装器将其转换为 .exe 文件,并使用 singleR3XPlayer 互斥锁在 Single instance 选项卡中选中“Allow only a single instance of the application”。

当我使用“退出”按钮关闭 .exe 文件时,一切都很好,javaw.exe 将终止。但是当我使用右上角窗口中的 X 按钮关闭 shell 时,javaw.exe 将继续运行。当我尝试删除 .exe 文件(Windows“使用的文件,仍然在 Java(TM) Platform SE 二进制文件中打开,关闭文件并重试”类型的错误弹出窗口)并且我无法打开时,我发现了这一点使用 X 按钮关闭文件后的另一个实例(因为单实例互斥锁)。此外,如果我执行一些 .jar 文件(即使在关闭它们之后,但仅使用 X 而不是“退出”按钮),javaw.exe 的多个实例将保持运行。

我发现用 X 按钮关闭窗口只会处理 shell 而不会退出程序。但是按下“退出”按钮会因为它调用 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 在应用程序关闭后终止。

希望有帮助。

于 2020-01-29T09:57:14.410 回答