I have a server written in Java that runs as a Windows service (thanks to Install4J). I want this service to be able to download the latest version of the JAR file it runs from, and start running the new code. The stitch is that I don't want the Windows service to fully exit.
Ideally, I would accomplish this by a unix-style exec() call to stop the current version and run the new one. How can I best accomplish this?
Here is a complicated, but portable, way.
Split your code into two jars. One very small jar is there just to manage process startup. It creates a ClassLoader that holds the other jar on its classpath.
When you want to load a new version, you terminate all threads running code from the old jar. Null out all references to instances of classes from the old jar. Null out all references to the ClassLoader that loaded the old jar. At this point, if you didn't miss anything, the old classes and ClassLoader should be eligible for garbage collection.
Now you start over with a new ClassLoader instance pointing at the new jar, and restart your application code.
As far as I know, there is no way to do this in Java.
I suppose you could work around it by using the Java Runtime.exec
or ProcessBuilder
's start() command (which start new processes) then letting the current one end... the docs state
The subprocess is not killed when there are no more references to the Process object, but rather the subprocess continues executing asynchronously.
I'm assuming the same is true if the parent finishes and is garbage collected.
The catch is Runtime.exec's process will no longer have valid in, out, and err streams.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With