Java并没有在应用程序关闭时释放所有资源

时间:2016-11-23 17:27:32

标签: java windows javafx firebird firebird-embedded

我有两个javafx应用程序,一个应用程序和更新程序。 应用使用Firebird数据库存储一些脆弱的用户数据。数据库以嵌入模式运行(我认为它是相关的),这意味着同时只能有一个与数据库的连接(数据库创建一个锁文件)。 更新程序更新应用程序。

整个架构如下所示:

  1. 用户运行App->应用程序正在检查是否需要更新,然后启动Updater(使用java ProcessBuilder)并自行关闭(Platform.exit())。
  2. 更新程序会检查应用程序是否已正确终止。
  3. 更新程序运行命令" App --export-user-data" (也使用ProcessBuilder)在开始更新之前导出最重要的东西(必须以这种方式完成 - 我无法将此功能移动到Updater)。
  4. 应用程序冻结第一个session.beginTransaction() - 没有单个错误或异常
  5. 到目前为止我所观察到的:

    • 当我启动App并按[X]然后全部关闭它 锁定文件来自" C:\ ProgramData \ firebird"被删除,但当App 启动Updater并关闭自己,然后锁定文件保持不变。我认为这就是Hibernate无法开始交易的原因。
    • 更新程序的进程不是App的子进程(我使用进程监视器检查了这个)
    • 当我直接启动Updater时,它就像魅力一样 - 所以问题只会在App启动更新程序时显示。

    我无法做的事情:

    • 将数据库切换到其他任何东西 - 它必须是firebird embedded
    • 将导出功能移至更新程序

    我会为最奇怪的想法而感到高兴,因为我花了四天时间试图解决这个问题。

    修改 火鸟版:2.1 Jaybird版本:2.1.6

    启动Updater的方式(仅限必要的东西)

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

1 个答案:

答案 0 :(得分:0)

经过长时间的战斗,我终于得到了解决方案。当java创建一个新进程时,子进程从它的父进程继承所有句柄。这就是火鸟锁文件尚未被删除的原因。我通过在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;
    }

}