JOGL javaw.exe продолжает работать после закрытия приложения

У меня есть простое Java-приложение, использующее JOGL. Когда я запускаю его из 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() возвращает 0 (нет ошибки) в конце initialize() и 0x502 (GL_INVALID_OPERATION) в начале destroy(). Между ними есть только основной цикл и никаких вызовов opengl, о которых я знаю, поскольку для тестирования я закомментировал весь код рендеринга.

Любые идеи?

Редактировать 3 октября 2012 г.:

Я до сих пор не знаю, в чем проблема, но поскольку я обновил драйверы своей графической карты, «javaw.exe» завершается, как и должно быть, после закрытия приложения. У меня AMD Radeon HD 6870. Моя текущая версия драйвера — 8.982 от 27 июля 2012 г., и я не могу вспомнить, какая была последняя версия, но я думаю, что она была выпущена примерно в январе 2011 года.

Однако glGetError() по-прежнему возвращает 0x502 в начале уничтожения, поэтому я предполагаю, что что-то не так.


person mrzli    schedule 29.09.2012    source источник
comment
Привет, взгляните на этот пример   -  person elect    schedule 12.08.2015


Ответы (2)


Если вы используете JOGL с сайта jogamp.org, пожалуйста, используйте либо наш SWT GLCanvas или наш NEWTCanvasSWT. Последнее предпочтительнее из-за пользовательских возможностей GLC, пожалуйста, проверьте документ API. Это плюс к тому, что вы делаете все, что связано с SWT в потоке SWT (читайте связанные модульные тесты), ИМХО, это должно работать - по крайней мере, наши модульные тесты.

Поскольку вы упомянули, что после обновления (графического процессора/драйвера) ваши проблемы прекратились, возможно, это была проблема с драйвером.

Теперь к вашей ошибке GL. Ошибки трассировки GL можно просто выполнить, установив системное свойство 'jogl.debug.DebugGL', то есть в командной строке "-Djogl.debug.DebugGL". Это автоматически установит конвейер отладки для вашего объекта GL и проверит наличие ошибки GL, которая вызовет исключение GLException, если появится.

Вы также можете выполнить трассировку через свойство jogl.debug.TraceGL.

person Sven Gothel    schedule 07.10.2012
comment
Прежде всего, спасибо за ваш ответ :). Я использую org.eclipse.swt.opengl.GLCanvas, он используется в каком-то примере, который я нашел, поэтому я также использовал его. Попробую те, что вы упомянули. Кроме того, «jogl.debug.DebugGL» ничего не делает в моем случае, хотя я все еще получаю код ошибки 0x502. Я новичок в java, поэтому я могу установить его неправильно - это то, что я делаю в начале основных свойств props = System.getProperties(); props.setProperty(jogl.debug.DebugGL, правда); - person mrzli; 12.10.2012

Я не знаю, актуально это или нет, но я думаю, что кому-то это может помочь, поэтому я поделюсь этим здесь. Имейте в виду, что я всего лишь любитель, начинающий работать с Java SWT.

Я сделал простое приложение в Eclipse IDE, используя библиотеку Java SWT. Я сделал кнопку «Выход» в моей основной оболочке окна, которая при нажатии вызывает это:

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

После экспорта файла .jar на рабочий стол я преобразовал его в файл .exe с помощью оболочки LaunchJ4 и установил флажок «Разрешить только один экземпляр приложения» на вкладке «Один экземпляр», используя мьютекс singleR3XPlayer.

Когда я закрывал файл .exe кнопкой «Выход», все было в порядке, и javaw.exe завершался. Но когда я закрывал оболочку с помощью кнопки X в правом верхнем углу окна, javaw.exe продолжал работать. Я понял это, когда попытался удалить файл .exe (Windows «Используемый файл, все еще открытый в двоичном файле Java (TM) Platform SE, закройте файл и повторите попытку» всплывающее окно с ошибкой) и поскольку я не мог открыть другой экземпляр файла после его закрытия с помощью кнопки X (из-за мьютекса Single instance). Кроме того, несколько экземпляров javaw.exe останутся запущенными, если я выполню несколько файлов .jar (даже после их закрытия, но только с помощью X, а не кнопки «Выход»).

Я понял, что закрытие окна с помощью кнопки 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 завершится после закрытия приложения.

Надеюсь, это поможет.

person P-A Fournier    schedule 29.01.2020