Java не освобождает все ресурсы при закрытии приложения

У меня есть два приложения javafx: приложение и средство обновления. Приложение использует базу данных Firebird для хранения некоторых хрупких пользовательских данных. База данных работает во встроенном режиме (я думаю, это актуально), поэтому это означает, что одновременно может быть только одно соединение с базой данных (база данных создает файл блокировки). Updater обновляет приложение.

Вся схема выглядит так:

  1. Пользователь запускает приложение-> Приложение проверяет, требуется ли обновление, если оно требуется, затем запускает Updater (с использованием java ProcessBuilder) и закрывается (Platform.exit ()).
  2. Программа обновления проверяет, правильно ли завершено приложение.
  3. Updater запускает команду «App --export-user-data» (также используя ProcessBuilder) для экспорта наиболее важных вещей перед запуском обновления (это должно быть сделано таким образом - я не могу перенести эту функцию в Updater).
  4. Приложение зависает на первом сеансе .beginTransaction () - нет ни одной ошибки или исключения

Что я наблюдал до сих пор:

  • Когда я запускаю приложение и закрываю его нажатием [X], все файлы блокировки из «C: \ ProgramData \ firebird» удаляются, но когда приложение запускает Updater и закрывается, файлы блокировки остаются нетронутыми. Думаю, поэтому Hibernate не может начать транзакцию.
  • Процесс обновления не является подпроцессом приложения (я проверил это с помощью монитора процессов)
  • Когда я запускаю Updater напрямую, он работает как шарм, поэтому проблема проявляется только тогда, когда приложение запускает Updater.

То, что я не могу делать:

  • переключить базу данных на что-нибудь еще - она ​​должна быть встроена в firebird
  • переместить функцию экспорта в Updater

Я был бы рад выдвинуть даже самые странные идеи, потому что я потратил четыре дня, пытаясь решить эту проблему.

изменить: версия Firebird: 2.1 Версия Jaybird: 2.1.6

Способ запуска Updater (только необходимое)

public void startUpdater(){
    ProcessBuilder pb = new ProcessBuilder(updaterPath, argument)
    pb.start();
    Platform.exit();
}

person straw    schedule 23.11.2016    source источник
comment
Пожалуйста, покажите минимальный код, необходимый для воспроизведения этого. Также включите встроенную версию Firebird и версию Jaybird, которую вы используете.   -  person Mark Rotteveel    schedule 23.11.2016
comment
Не видя никакого кода, я думаю, вам следует корректно завершить работу приложения, а не просто вызывать exit ().   -  person Henry    schedule 23.11.2016
comment
Я не могу опубликовать исходный код, потому что он мне не принадлежит, но я постараюсь предоставить несколько фрагментов. Я также расскажу больше о firebird.   -  person straw    schedule 23.11.2016
comment
Вызов Platform.exit(), скорее всего, завершает работу приложения и - iirc - дочерних приложений. Это, вероятно, означает, что встроенный Firebird не завершает работу должным образом, а также может означать, что процесс, запущенный с использованием ProcessBuilder, также будет остановлен.   -  person Mark Rotteveel    schedule 24.11.2016


Ответы (1)


После долгой битвы я наконец нашел решение. Когда java создает новый процесс, дочерний процесс наследует все дескрипторы от своего родителя. И поэтому файлы блокировки firebird не были удалены. Я решил это, создав небольшое приложение в cpp и используя его в качестве прокси при запуске программы обновления.

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

int _tmain( int argc, TCHAR *argv[] )
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );

    if( argc != 2 )
    {
        printf("Usage: %s [cmdline]\n", argv[0]);
        return 0;
    }

    // Start the child process. 
    if( !CreateProcess( NULL,   // No module name (use command line)
        argv[1],        // Command line
        NULL,           // Process handle not inheritable
        NULL,           // Thread handle not inheritable
        FALSE,          // Set handle inheritance to FALSE
        0,              // No creation flags
        NULL,           // Use parent's environment block
        NULL,           // Use parent's starting directory 
        &si,            // Pointer to STARTUPINFO structure
        &pi )           // Pointer to PROCESS_INFORMATION structure
    ) 
    {
        printf( "CreateProcess failed (%d).\n", GetLastError() );
        return 0;
    }

}
person straw    schedule 24.11.2016