用Java打开新进程并保持当前进程为打开状态

时间:2019-01-11 14:00:08

标签: java processbuilder filelock

有一个任务可以使我们的软件的新版本发布到新客户端,我需要使应用程序表现为正常运行,最初启动的应用程序将启动另一个应用程序,并始终保持打开状态。此刻,当新的开始时,原来的关闭。原始应用程序是一种加载程序,其整个目的是从服务器下载其他应用程序并运行其中一个。这就是为什么使用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();
}

TryLock:

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中,我可以通过仅返回返回值替换tryLock()的内容,并在Processbuilder的命令中添加waitFor()来使应用程序正常工作。在Windows中,新应用程序直到第一个被杀死后才启动。

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

2 个答案:

答案 0 :(得分:0)

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

我会尽量避免文件锁定,而仅监视子进程

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

答案 1 :(得分:0)

因此,我必须使用ProcessBuilder的InheritedIO方法才能打开新进程。现在它可以按预期工作了。还为流程添加了waitFor():

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