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