3

I am building some kind of an updater function in my program. When an update is detected, the program should download an updater.jar and terminate. After that, the updater.jar will download a new version of the program and delete the old one. This is how my main program runs the updater:

Runtime.getRuntime().exec("java.exe -jar updater.jar "+updateURL+" "+workingPath);
System.exit(0);

However, for some reason, the System.exit(0) doesn't get called until the updater is done... and the updater can't remove the old version of the main program while it's running. Result: everything starts hanging.

Anyone got an idea how to tell my main program /not/ to wait for the updater to terminate before calling System.exit(0)?

EDIT:

FileUtils.copyURLToFile(url, file);
System.out.println("Downloading updater...");
new Thread() {
    public void run() {
        try {
            Runtime.getRuntime().exec("java.exe -jar updater.jar "+updateURL+" "+workingPath);
        } catch (IOException ex) {
            System.out.println("Exception: " + ex.getMessage());
        }
    }
}.start();
System.out.println("Shutting down application.");
System.exit(0);

Cmd displays the "Shutting down application.", but the jar doesn't seem to be shutting down until I manually kill the process.

Kelly
  • 40,173
  • 4
  • 42
  • 51
Laurent Loots
  • 145
  • 2
  • 16
  • can't you run `Runtime.getRuntime().exec("java.exe -jar updater.jar "+updateURL+" "+workingPath);`on a separate detached thread – Abdullah Al-Hatem Jan 03 '14 at 14:43
  • even if you run the exec in a background thread, won't calling System.exit() try to kill the process? – dkatzel Jan 03 '14 at 14:58
  • I tried adding a few lines after System.exit(), they don't get displayed, so either he's just hanging there or the VM just won't leave the JAR alone, it still can't be deleted and gives the error that it's "in use". – Laurent Loots Jan 03 '14 at 15:02

5 Answers5

0

Try with Apache Common Exec. It has the ability to asynchronously execute a process.

Another option is to run the

Runtime.getRuntime().exec("java.exe -jar updater.jar "+updateURL+" "+workingPath);

in a separate thread using a Runnable/Callable. Also, it would be helpful for you to look at this SO thread (shows how to use the ProcessBuilder).

Community
  • 1
  • 1
  • Tried your code. It runs the updater, but still the system.exit(0) doesn't get called... Updated my code in main thread. – Laurent Loots Jan 03 '14 at 14:51
0

I think you can just use ProcessBuilder like so;

String[] cmd = { "java.exe", "-jar", "updater.jar", updateURL, workingPath };
ProcessBuilder pb = new ProcessBuilder(cmd);
try {
  Process p = pb.start();
} catch (IOException e) {
  e.printStackTrace();
}
System.exit(0);

You might also use SwingUtilities to invokeLater() like so

javax.swing.SwingUtilities.invokeLater(new Runnable() {
  @Override
  public void run() {
    Runtime.getRuntime().exec(
      "java.exe -jar updater.jar " + updateURL + " "
          + workingPath);
    }
  }
);
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
0

The JVM process running the updater.jar is distinct from the JVM process you are running the Runtime.exec(..) command with. If you want to wait for the updater.jar process to finish (or kill it after a timeout), have a look at Process.waitFor().

Jukka
  • 4,583
  • 18
  • 14
0

I fixed it by just throwing an uncaught exception. It made the program exit, and the updater could go on with its business.

Perhaps not the most pretty way to do it, but it works :)

Laurent Loots
  • 145
  • 2
  • 16
0

Found the source of the problem:

My checkForUpdate() was called from my constructor, calling it after the constructor fixed the entire thing. The jar shuts down and updates correctly now :)

Laurent Loots
  • 145
  • 2
  • 16