【问题标题】:JOGL javaw.exe remains running after application is closed应用程序关闭后,JOGL javaw.exe 仍然运行
【发布时间】:2020-02-03 01:19:10
【问题描述】:

我有一个使用 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 年 7 月 27 日的 8.982,我不记得最后一个版本是什么,但我相信它是从 2011 年 1 月左右开始的。

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

【问题讨论】:

标签: java opengl jogl


【解决方案1】:

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

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

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

您还可以通过属性“jogl.debug.TraceGL”进行跟踪。

【讨论】:

  • 首先,感谢您的回复:)。我正在使用 org.eclipse.swt.opengl.GLCanvas,它被我发现的一些示例使用,所以我也使用它。我会试试你提到的那些。在我的情况下,“jogl.debug.DebugGL”也没有任何作用,而我仍然收到错误代码 0x502。我是 java 新手,所以我可能设置错了 - 这是我在 main Properties props = System.getProperties(); 开头所做的事情props.setProperty("jogl.debug.DebugGL", "true");
【解决方案2】:

我不知道这是否相关,但可能会对我猜的人有所帮助,所以我将在这里分享。请记住,我只是 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 文件,javaw.exe 的多个实例将保持运行(即使在关闭它们之后,但仅使用 X 而不是“退出”按钮)。

我发现用 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 在应用程序关闭后终止。

希望对您有所帮助。

【讨论】:

    猜你喜欢
    • 2013-02-03
    • 2011-04-02
    • 2021-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-03
    • 1970-01-01
    • 2021-04-20
    相关资源
    最近更新 更多