Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I replace the current Java process, like a unix-style exec?

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?

like image 440
Alex Avatar asked Nov 15 '22 16:11

Alex


2 Answers

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.

like image 166
Darron Avatar answered Dec 01 '22 00:12

Darron


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.

like image 30
Powerlord Avatar answered Nov 30 '22 22:11

Powerlord