I have a simple test run of some medium-complexity code that won’t terminate, i.e. the main method finishes but the process does not die.
Here is a rundown of the code (which is too long to be pasted here):
ProcessBuilderis used to create a bunch of subprocesses. They all die properly (if you can believe VisualVM).- We use log4j.
- The main algorithm runs inside a
FutureTaskon whichrunand latergetare called. - We don’t explicitly use RMI, even though the list of threads seems to suggest so.
Obviously, I can call System.exit(0), but I’d like to know what is amiss here. I have not been able to produce a minimum failing example. Also, I can not identify an obvious culprit from the thread list; maybe you can?

Edit: See here for a thread dump.
Scorpion lead me to the right answer:
RMI Reaperis something like a garbage collector for remote objects, e.g. instances of (subclasses of)UnicastRemoteObject. It is a non-daemon thread and therefore blocks JVM termination if there are still exported objects which can not be cleaned up.You can explicity force remote objects to be cleaned up in this sense by passing them to
UnicastRemoteObject.unexportObject(., true). If you do this on all previously exported objects,RMI Reaperterminates and JVM is free to shut down.