Reputation: 15547
I have an application that consists of a JRE (or custom runtime image, as the jlink docs call it), a JAR file, and a method to run the JAR on the JRE (either a bash or batch file or an exe or .app package).
I want to send out updates for the application (which is working, I can connect to my server and download newJRE.zip and newJAR.jar), but I don't know the best way to replace the currently running JRE with the new JRE.
I've tried unzipping the new JRE to a seperate folder, using ProcessBuilder to restart my JAR on the new JRE, then calling System.exit() on the original JRE and from the new JRE deleting the old JRE and copying the new JRE to the original location, and finally restarting my app again on that JRE. That didn't work (on Windows, I haven't tried yet on Linux or Mac) because the new, restarted JRE appears to be holding file locks (or handles?) on some of the files in the old JRE, so it can't delete them. I also tried running a batch file that deletes the old JRE and replaces it with the new one, but again it is also unable to delete all the files in the old JRE.
Can this be done in Java, or do I have to write my update logic for each platform separately? What's the best way to do it?
Upvotes: 2
Views: 375
Reputation: 9461
In theory in can be done but in practice there are hurdles.
One of them is that on Windows, as long as some executable is executing the file on disk is write-protected. On Unix this is not the case. And yet there may be strange effects if you manage to update half the application/JDK before something goes wrong.
I have not really checked but believe all applications that come with autoupdate features circumvent this problem by actually consisting of two applications. One of them is a thin wrapper that checks for updates and gets them installed, then starts the real application.
If you want this for Java the thin wrapper already exists and is called WebStart. Since Java 9 Oracle no longer supports it, but then there is https://openwebstart.com/
Upvotes: 0