在 Java 中打开新进程并保持当前进程打开

Opening new process in Java and keeping current one open

有一项任务是为新客户端制作新版本的软件,我需要让应用程序表现得如此,最初启动的应用程序启动另一个应用程序并在后面保持打开状态。目前,当新的开始时,原始的关闭。原始应用程序是一种加载器,它的全部目的是从服务器下载其他应用程序,运行 其中之一。这就是使用 FileLock 的原因,这可能是我无法弄清楚如何在后面保持原件打开并成功打开新文件的原因。我设法在 Linux 中完成了这项工作,但不幸的是我们的客户使用 Windows 10...

一些变量:

private final List<FileLock> locks = new ArrayList<FileLock>();
private final File applicationPath;
private final String application;

加载器构造函数

public Loader(String[] args) throws IOException {
    this.args = args;

    applicationPath = new File(THIS_DIRECTORY, application + ".jar");

    tryLock("loader");
    tryLock(application);
}

load() 是在构造函数创建后在 main 中调用的,没什么特别的。

private void load() throws Exception 
    checkAndDownloadUpdate(application, applicationPath);

    String javaBin = getJavaBinary();
    List<String> command = new ArrayList<String>();
    command.addAll(Arrays.asList(javaBin, THIS_FILE.getAbsolutePath(), "-jar", applicationPath.getAbsolutePath()));
    command.addAll(Arrays.asList(args));

    new ProcessBuilder(command).start();
}

尝试锁:

private void tryLock(String name) {
    File path = new File(THIS_DIRECTORY, name + "_lock");
    long waitUntil = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(10);
    while (System.currentTimeMillis() < waitUntil) {
        try {
            FileLock fileLock = tryLock(path);
            if (fileLock != null) {
                locks.add(fileLock);
                return;
            }
        }
}

在 Linux 中,通过仅用 return 替换 tryLock() 的内容并将 waitFor() 添加到 Processbuilder 的命令,我能够使应用程序按我想要的方式工作。在 windows 中,新应用程序只有在第一个应用程序被终止后才会启动。

启动新进程时似乎会出现问题,在 Windows 10 Java 调用 Unsafe.park() 方法并停止,直到原始进程关闭。

我认为这是因为 Windows 中的文件句柄会阻止第二个进程获得对该文件的锁定。 只有当第一个进程释放它的锁时,第二个进程才能获得它。

我会尽量避免文件锁,只监控子进程

ProcessBuilder builder = new ProcessBuilder("comman.exe");
Process process = builder.start();
if (process.isAlive()) {
  //wait
 }

所以我必须让 ProcessBuilder 的 inheritIO 方法能够打开新进程。现在它按预期工作。还为进程添加了 waitFor():

    ProcessBuilder builder = new ProcessBuilder(command);
    builder.directory(new File(workingDir.toString()));
    builder.inheritIO();
    Process p = builder.start();
    p.waitFor();