References

by Dr. Heinz M. Kabutz

Welcome to the 98th edition of The Java(tm) Specialists' Newsletter. Did you know that
the world is split into six floral kingdoms? The largest in
size is the Holarctic Kingdom (42%), consisting of North
America and Eurasia. The smallest is Capensis (0.04%)
consisting of Cape Town and surrounding areas. Down here at
the most south-west part of Africa, we have the greatest
density of diverse plant life on the planet, which we
generically call "fynbos". This is wonderful for plant
lovers, but terrible for hayfever sufferers like me. If it
was up to me, I would chop down all the fynbos and cover it
all with concrete! [ok, I know I made enemies with that
statement, but if we could swap bodies for one week, you
would agree with me ;-]

I usually run my Java
courses at the Faculty Training Institute
in Cape Town. From our balcony, we overlook the Kenilworth
Race Track. When the horse racing track was built, the
inside of the track was kept in its original state. This is
the last remaining habitat of some micro frogs living in the
original fynbos. What happened was that the horse race track
guarded the original plants, protecting them from the alien
plant invasion from Australia.

References

How many articles have you read about soft, weak and phantom
references? How many of those did you understand? I tried,
and found most of the articles extremely hard to make sense
of. This is an attempt to explain some of the behaviour of
soft and weak references, and then to invent a new type of
references that is, dare I say, more useful than a weak
reference?

Soft vs Weak References

In newsletter 15,
I described a SoftReference based HashMap, where
the values were embedded in soft references. (The
WeakHashMap has the keys embedded in weak references,
so that would not be useful for building a cache.) At the
time of writing, I was using JDK 1.3.x, and I did not notice
any difference in the behaviour of soft vs. weak references.
It turns out that there appeared to be some design flaw in
JDK 1.3.x that rendered SoftReferences useless in the Sun JVM.
Consider the following test code:

We need to run this with the various JVMs. Very few
companies still use JDK 1.2.x, so I will not consider that
case. In addition, I could not find a difference between
JDK 1.4.x and JDK 1.5.x, so will only compare JDK 1.3.x with
JDK 1.5.x.

Let us start by looking at Sun JDK 1.3.1_12. When we run the
code, we can see that soft and weak references are released
at about the same time. This is not dependent on how many
references we have. It does not matter whether we have 10 or
1000 references. The JavaDocs (hard to understand) of the
reference classes seem to hint that weak references should be
released before soft references. However, in JDK 1.3.x, this
was not the case:

The JDK 1.5.0 behaves more closely to what we would expect.
When we run the code, we can see that weak references are
typically released first, and soft references are mainly
released when the memory becomes low:

I put this observation to Mark Reinhold, who was kind enough
to send me a quick response:

> [I know you are busy, so a simple: "Yes, JDK 1.3.x had a useless
> implementation." will suffice :-]
In fact that's exactly the case. HotSpot didn't have a useful
implementation of soft references until 1.4.

There we go. From the author of the java.lang.ref package
himself. No wonder Sydney and I needed such a strange
approach in newsletter 15.

New SoftHashMap

I then wrote a new SoftReference based HashMap, but this time
based on generics, and using my discoveries of the behaviour
of the new SoftReferences. (Thanks to Jason Walton for pointing
out two possible memory leaks in the original code.)

GhostReference

Did you know that you can write your own reference? A few
months ago, I was having dinner at Mariner's Wharf in the
village of Hout Bay near Cape Town, with three of Sun's Java
evangelists. One of the points of discussion was that none
of us had ever found a good use for the PhantomReference.
The only suggestion that I could come up with is with object
counting, and to use it to determine when objects are
garbage collected (newsletter
38).

I spent several hours today thinking about PhantomReference.
I did a search on google and could not find any good use case
for the PhantomReference. On very careful inspection, I
discovered some differences between the phantom and weak
references. Both are released rather quickly, but the
phantom reference is enqueued in the reference queue before
it's referent is cleared, whereas the weak reference is
enqueued after the referent is cleared. One hitch -
the PhantomReference.get() method always returns
null. Hah - time for reflection!
Another difference is that the PhantomReference is enqueued
only after the finalize() method has
been called.

Another hitch with references is this: If you want the
reference to be added to the reference queue, you have to
keep a strong reference to the reference. To solve
this problem, I keep a Collection of currently active
references inside my GhostReference. As is the case with all
PhantomReference objects, you have to call clear() on the
reference once you have completed working with it.

We now have a more sensible Reference, with a cool name.
It is not necessary to have a strong reference to the
Reference object, in order for it to be enqueued, and it is
possible to get hold of the referent (the object that we want
a reference to) from the enqueued Reference:

Warning: the PhantomReference is only called after the finalize()
has completed. This means that we are resurrecting an object that
will then never be finalized again. However, this is only a
theoretical limitation, as in practice you should never use
the finalize() method anyway.

I have still to this day (2009-11-12) not used the PhantomReference
in real programming work. What is interesting is that it is also
not used once in the whole of the JDK, whereas both weak and soft
references are. The WeakReference is subclassed in order to
implement Finalizers.

Kind regards

Heinz

P.S. If you can come up with a miracle cure that will solve
my hayfever, I will reconsider my stance on the fynbos
eradication ;-)

P.P.S. The fynbos is safe - I moved to Crete in Greece in 2006,
which has a lot less pollen in the air.

Oracle and Java are registered trademarks of Oracle and/or its
affiliates. Other names may be trademarks of their respective
owners. JavaSpecialists.eu is not connected to Oracle, Inc.
and is not sponsored by Oracle, Inc.