Java shutdown hook没有启动我的Process

时间:2017-09-15 11:14:51

标签: java launch shutdown-hook

我试图为我的应用提供自我更新功能。 它从我的网站下载JAR并将其保存为myapp.jar.new

之后,我想启动一个命令来删除当前版本并重命名新版本。

这是我的代码(见注释):

public void applyUpdateAndRestart() {
    Runtime rt = Runtime.getRuntime();
    rt.addShutdownHook(new Thread(() -> {
        try {
            String updateCmd = "restart.cmd";
            try (PrintStream ps = new PrintStream(new FileOutputStream(updateCmd))) {
                ps.println("@echo off");
                // wait for a while to the main process closes and the "myapp.jar" to be writable
                ps.println("ping 127.0.0.1 -n 2 > nul"); 
                ps.println("del /q myapp.jar.old");
                ps.println("move myapp.jar myapp.jar.old");
                ps.println("move myapp.jar.new myapp.jar");
                ps.println("java -jar myapp.jar");
            }

            ProcessBuilder p = new ProcessBuilder();
            p.command("cmd", "/c", updateCmd);

            System.out.println("Before apply update");

            p.start(); // this does not launch

            System.out.println("After apply update"); // this prints!
        } catch (Throwable e) {
            e.printStackTrace(); // this does not occurs!
        }
    }));
    System.exit(0);
}

为什么我的update.cmd无法启动?

3 个答案:

答案 0 :(得分:1)

用这种方法解决:

  • 将我的jar下载到new-myapp.jar之后,我使用这样的特殊参数启动它:java -jar new-myapp.jar --do-update(运行新jar将解锁当前的覆盖)
  • 我的main mehtod拦截了将新jar应用于当前(--do-update)的参数copy new-myapp.jar myapp.jar
  • 复制新jar后,使用覆盖的jar(java -jar myapp.jar)再次启动自己

我认为Klitos comment也可以解决我的问题,但我解决了我以前的方法。

问题的解决方法是问题是cmd /c没有分配控制台窗口。将命令更改为cmd /c start也可以解决问题,因为start命令会分配新的控制台窗口。

答案 1 :(得分:0)

我的想法 - 因为你只需要调用start()来处理进程并完成关闭钩子 - 这个进程会因你的主java进程而死掉。尝试调用Process.waitFor()让你关闭挂钩线程,等待外部进程完成。

答案 2 :(得分:0)

我认为你不能像你想的那样去做。您想要删除应用程序的jar但应用程序正在运行,因此无法删除。

我的建议是使用launcher.cmd查找new.jar,如果它发现它删除old.jar并重命名new.jar然后启动java -jar old.jar。