TCCL memory leak in RMI registry creation

Stuart Marks stuart.marks at oracle.com
Mon Apr 25 21:26:18 UTC 2016



On 4/22/16 3:03 AM, Mark Thomas wrote:
> Excellent. Thank you very much for that. It does indeed work.

Glad to hear it!

>> It's probably necessary to unexport and maybe also unbind everything
>> from this registry as well, as Roger had suggested previously.
>
> For the record, if the module/application creates the registry,
> unexporting the registry is sufficient. However, an additional GC cycle
> is required to clean up the references if unexport and unbind are not
> called.

Hm. That might be the case for this test program, but in general, I'm concerned 
it might not be sufficient.

There's no requirement in RMI that every exported object be in the registry. If 
a remote object is exported, and another JVM has a stub that references this 
remote object, that object will be kept alive indefinitely by DGC. Clearing out 
the registry won't help with this.

> The good news is that, with the information above, this leak is
> something that modules/applications can and should do something about.

I think the general rule has to be that, if an application has exported a remote 
object, that object should be unexported when the application shuts down. This 
applies equally well to registry objects created by the application.

Unfortunately doing this in RMI is probably uncommon practice, since most 
documentation, tutorials, examples, etc. only cover bringing up an RMI service, 
and they don't cover shutdown. For example, the Java Tutorial on RMI [1] doesn't 
seem to talk about this issue at all. I suspect that most examples out there 
assume that RMI services will run for the lifetime of the JVM. Most applications 
simply follow this and probably don't include any logic for cleaning up after 
themselves.

[1] http://docs.oracle.com/javase/tutorial/rmi/overview.html

> This moves the problem to how to detect when modules/applications fail
> to clean up an RMI Registry they created. I'd like to be able to provide
> nice loud error messages when this happens. Open questions are:
> - How to get a list of RMI registries?
> - How to determine the TCCL for a registry (held in the ccl field of the
>   associated sun.rmi.transport.Target object) so I can figure out if a
>   module/application created it?

I don't have a good answer for this.

I do think that talking about registries is a bit of a distraction. As I 
mentioned above, the general problem can occur with any remote object, and a 
registry is mostly an ordinary remote object.

All remote objects in this JVM are kept in the ObjectTable, and the cleanup code 
you have looks through this for Target objects with the right ccl etc. already.

If you want the cleanup function to continue to be active in production use of 
Tomcat, then you'll probably need to explore the JVM command-line options that 
enable the reflective access to continue, e.g. -XaddExports or -Xpatch.

A variant of this is to get one's hands on the remote object itself and then 
call unexportObject() on it, instead of directly removing things from the 
various maps. This probably does the cleanup in a more robust fashion, though it 
doesn't help with the main problem of getting reflective access.

If this doesn't need to run in production, and can be run only in, say, some 
"diagnostic mode," (not sure if such a thing exists) then there are some other 
possibilities. For example, one might load an agent, or use the debugger 
interface, to track remote objects being exported and unexported. If, after 
shutting down an application, remote objects remain exported, this could cause 
some errors to be issued.

s'marks



More information about the core-libs-dev mailing list