在 Java 中打开新进程并保持当前进程处于打开状态

Posted

技术标签:

【中文标题】在 Java 中打开新进程并保持当前进程处于打开状态【英文标题】:Opening new process in Java and keeping current one open 【发布时间】:2019-06-06 11:06:02 【问题描述】:

有一项任务是为新客户制作我们软件的新版本,我需要让应用程序的行为如此,最初启动的应用程序会启动另一个应用程序并在后面保持打开状态。目前,当新的开始时,原来的就关闭了。原始应用程序是一种加载器,其全部目的是从服务器下载其他应用程序并运行其中一个。这就是使用 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 中,通过将 tryLock() 的内容替换为 return 并将 waitFor() 添加到 Processbuilder 的命令中,我能够使应用程序按我的意愿工作。在 Windows 中,新应用程序在第一个被杀死之前不会启动。

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

【问题讨论】:

【参考方案1】:

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

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

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

【讨论】:

也不起作用,在第一个进程被杀死之前不会打开另一个进程。【参考方案2】:

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

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

【讨论】:

以上是关于在 Java 中打开新进程并保持当前进程处于打开状态的主要内容,如果未能解决你的问题,请参考以下文章

JAVA多线程

Windbg Processes and Threads(进程和线程)窗口的使用

如何修改ulimit参数pending signals

内核参数:ulimit详解

如何在父进程被杀死/完成时保持子进程处于活动状态(在 Windows 中)

在进程间传递文件描述符