[java-gnome-hackers] The next stage in memory management
Brought to you by:
afcowie
|
From: Andrew C. <an...@op...> - 2010-01-08 06:30:56
|
Way back in the dark ages, we started the current version of java-gnome.
We [especially Vreixo] invested a huge amount of time in getting the
memory management correct, specifically the use of ToggleRefs to manage
the reference count that a java-gnome proxy has on a GObject, while
being able to return the existing proxy for a GObject if there is one,
using WeakReferences and the JNI equivalent. Magic no end.
Through extensive experience, that work has held up nicely.
If you were to look in the base class Pointer, you'd see a nice little
fragment I wrote four or so years ago as follows:
/**
* Parent release function. Will be called by the Java garbage collector
* when it invokes the finalizer, so this is the time to release
* references and free memory on the C side.
*/
protected abstract void release();
/*
* This is a placeholder to remind us of the cleanup actions that will be
* necessary, irrespective of the finalizer technique used.
*/
protected void finalize() {
release();
}
Right from the get-go, I knew that we'd have to have our own code path
to free resources, and I also knew full well that Java's finalize()
mechanism is "unreliable" and that really if you need to clean up after
yourself you should be using PhantomReferences (or WeakReferences or
SoftReferences, depending).
Now, what most people meant when they talk about "unreliable" is that
they are not "guaranteed" to be called; a number of circumstances
[/implementations] just terminate the Java VM process without calling
the finalizers of every bloody object. So if (say) you're holding on to
database client connections, they won't necessarily get cleared /
closed / etc. Bad.
In normal usage, though, finalizers *do* indeed get called, and for our
purposes they were fine. And so the placeholder above has been doing us.
I've started to run into a circumstance where this is not ideal,
however. I'm doing something that is [org.gnome.pango] Layout &
LayoutLine heavy; down in Pango itself these use a lot of resources;
ordinarily that's fine because they are transient, but the thing I am
working on is generating a *lot* of them, and they aren't getting
free()'d until ... well, last time I ran the app I got myself > 100 MB
of writable memory before a full GC happened. Yeech.
The problem is that the full Java garbage collector [and I'm talking
about OpenJDK HotSpot here] does not ordinarily run until the VM thinks
it is out of heap. And that isn't going to happen anytime soon on most
systems. Which means that finalize() isn't get called until *MUCH* later
than we'd like, and we're holding on to tons of memory (allocated by
glib) unnecessarily.
Telling people just to call System.gc() doesn't really seem to address
the weakness.
Which brings us back to the _other_ purpose of SoftReference,
WeakReference, and PhantomReferences: taking actions on Java objects as
they go through the lifecycle, including being able to do cleanup long
before finalize() gets called by the GC in it's second last phase.
See file:///usr/share/doc/openjdk-6-doc/api/java/lang/ref/package-summary.html#reachability
for more details.
Presumably we want another WeakReference, plus a ReferenceQueue. The
question is: what will poll the reference queue, and when?
Sometime people use a separate thread for that. Another possibility
would be to use an idle handler setup from the native side. A third
option would be to poll the reference queue as a (generated) part of
every JNI call.
Thoughts?
AfC
Sydney
P.S. What I *really* want to do is override g_object_ref() and
g_object_unref(), but that'd only be possible with a LD_PRELOAD hack.
But if they were plugable, and in conjunction with setting the Glib
allocator function [which is plugable] to use (say) direct buffers, we
could really get cool about leak detection on both sides. But that's
another project.
--
Andrew Frederick Cowie
Operational Dynamics is an operations and engineering consultancy
focusing on IT strategy, organizational architecture, systems
review, and effective procedures for change management: enabling
successful deployment of mission critical information technology in
enterprises, worldwide.
http://www.operationaldynamics.com/
Sydney New York Toronto London
|