RMI Threads prevent JVM from exiting after main() completes RMI Threads prevent JVM from exiting after main() completes multithreading multithreading

RMI Threads prevent JVM from exiting after main() completes


Sure enough, I had a bug in the code that caused one of my (many) UnicastRemoteObjects to not unexport itself when the calling application was done utilizing it. So the answer is:

Unexporting all UnicastRemoteObjects within a running JVM is sufficient to close all RMI non-daemon threads.


Sounds like you solved you problem @Ben but for posterity, I thought I'd promote my comment to an answer. Whenever I have a register/unregister type of pattern I make sure to manage them through a singleton object. This way you have one place to go to figure out which object was not unregistered. Exposing this in JMX is also a win.

Something like the following code would be good. It will allow you to log or JMX query to see what objects have been bound to the registry but have yet to be unbound.

public class UnicastRegistry {    private static Registry registry;    private static UnicastRegistry singleton;    // private to force the singleton    private UnicastRegistry() throws RemoteException {        registry = LocateRegistry.createRegistry(9977);    }    public static UnicastRegistry createSingleton() throws RemoteException {        if (singleton == null) {            singleton = new UnicastRegistry();        }        return singleton;    }    public void register(String label, Remote obj) throws Exception {        registry.bind(label, obj);    }    public void unregister(String label) throws Exception {        Remote remote = registry.lookup(label);        registry.unbind(label);        if (remote instanceof UnicastRemoteObject) {            UnicastRemoteObject.unexportObject(remote, true);        }    }    public void unregisterAll() throws Exception {        for (String label : registry.list()) {            unregister(label);        }    }    public void printStillBound() throws Exception {        String[] stillBound = registry.list();        if (stillBound.length > 0) {            System.out.println("Still bound = " + Arrays.toString(stillBound));        }    }}