To make a long story short, I'm having trouble getting a couple of Java RMI's non-daemon threads to close out after my application no longer needs RMI. This prevents the JVM from exiting when main() completes.
I understand that exporting UnicastRemoteObject
s will cause RMI to leave threads open until you successfully call UnicastRemoteObject.unexportObject(Object o,boolean force)
. Here's an example (run without modification and the JVM will exit normally - remove the call to unexportObject and the JVM will never exit):
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
public class TestUnicastRemoteObject{
private static UnicastRemoteObject obj;
private static Registry registry;
public static void main(String[] args) throws Exception{
obj = new UnicastRemoteObject(){
private static final long serialVersionUID = 1L;
};
System.err.println("created UnicastRemoteObject");
System.err.println("creating registry ...");
registry = LocateRegistry.createRegistry(9999);
System.err.println("registry created.");
System.err.println("binding obj to registry ...");
registry.bind("Test", obj);
System.err.println("bound");
UnicastRemoteObject.unexportObject(obj, true);
System.err.println("unexported obj");
}
}
Also, it doesn't seem to matter whether you create the registry and/or bind the remote object to it - the only thing that seems to matter in this example is that any time you create a UnicastRemoteObject, you need to call unexportObject
in order to prevent any threads from remaining after you're done.
In my application, I've made sure that I've called unexportObject on every UnicastRemoteObject I create, and yet RMI's "reaper" thread and "connection accept" thread still persist, preventing my JVM from exiting when my application is finished using RMI resources.
Is there something else that could cause RMI to leave threads behind, aside from forgetting to unexport UnicastRemoteObjects?
UnicastRemoteObject.unexportObject(obj,true)
. The desired behavior is for the test program to exit. I suspect I am probably missing a call to unexportObject somewhere, but was just curious if there are any other ways to leave RMI threads running. – Infidelitybind()
operations through some internal API so you can track which objects you have yet to un-bind. Never call the registry directly except through the manager singleton. Keep a map of them or something (maybeIdentityHashMap
) and remove them when youunexportObject
. – Debacle