Java News Brief
June 2000 Issue
Headlines:
Java
Technical Insight of the Month
Collaborating
with the Java Memory Manager
Visit The
Java News Brief Archive for past issues of the JNB.
OCI
Educational Services
Java Technical Insight of the Month
Collaborating with the Java Memory Manager
By Brian Gilstrap, Principal Software Engineer, Object
Computing, Inc. (OCI)
Java developers are all familiar with the Java garbage
collector, which eliminates the need to explicitly deallocate objects.
However, few know that there is a package in Java 2[TM] (JDK 1.2 and later) which
allows them to coordinate their activities with the garbage collector. This
package java.lang.ref, provides a number of classes to allow developers
some interaction with garbage collector. To understand how these classes
are useful, we must first understand the different types of references.
Types of Object References
All developers use object references when programming. For example, the
following line of Java code declares a reference to a String and makes it refer
to a string object with contents "hello":
String aHelloString = "hello"
The variable aHelloString is an object reference. In order to distinguish these garden variety object references from the other kinds of references we will be discussing, Java calls this kind of reference a strong reference. This is because the String object referred to by aHelloString is held onto "strongly", meaning it can't be garbage collected as long as it is referred to in this manner.
In addition to normal, strong references, there are three
other kinds of references that Java 2[TM] provides. They provide
increasingly "weaker" kinds of references, meaning that each successive type
of reference places fewer restrictions on the garbage collector. These three
types of references are:
All of these reference types share certain common characteristics:
These other kinds of references are created by creating an instance of one of
the reference classes in the java.lang.ref package (SoftReference,
WeakReference, or PhantomReference). There is also a java.lang.ref.Reference
class but it is an abstract base class for the other three and cannot be
instantiated.
Let’s look at an example,. The following line of code
corresponds to Figure 1:
Reference aRef = new SoftReference( new
String( “foo” ) );

Figure 1
While we created a SoftReference in the code, we could have created a
WeakReference or a PhantomReference and achieved essentially the same state of
affairs.
By looking at Figure 1, we can see that these new kinds of
reference objects add overhead in terms of space (there is another Java object
on the heap, the reference object), and they also cost us some time (the garbage
collector interacts with these references in certain ways, which takes
time). This leads us to a question: what features do these references
offer that would make it worth the time and space to use them? To
understand this, we need to look at each kind of reference.
Soft References
Soft references are good for providing caches of objects which can be garbage
collected when the Java Virtual Machine (JVM) is running low on memory. In
particular, the JVM guarantees a couple of useful things:
This allows us to use soft references to refer to objects that we could afford
to have garbage collected, but which it is convenient to have around until
memory becomes tight. Obviously, this means our program has to be able to
live without these objects or be able to recreate them. But we can let the
garbage collector decide when to collect these objects, continuing the Java goal
of letting the programmer avoid explicit memory management.
There is no specific timeframe after an object "goes soft"
(becomes reachable through soft references but not through strong references)
when the garbage collector will collect the object, but the documentation
encourages JVM implementors to prefer collecting older objects and to delay
collection as long as is feasible.
Weak References
Weak references are good for providing "canonicalizing mappings".
These are mappings from some unique identifier to an object. For example,
imagine we have permanent storage (a file, database, etc.) containing a large
number of Employee objects, and that we only work with a subset of them at any
given time (perhaps there are too many to fit in a running JVM on the machines
we have, and we only need to work with a small number of them at any given
time). Assume that we uniquely identify employees by an employee
number. We could use weak references to refer to all employee objects
currently in the JVM and provide a Map (or HashTable) which maps from the
employee number to a weak reference to the corresponding Employee object (see
Figure 2).

Figure 2
When using this sort of approach, we have a "canonical" mapping between the
employee number and the Employee object, meaning there is a one-to-one
correspondence between employee numbers as keys in the map, and Employee objects
which have that employee number.
We would not want to prevent an Employee object from being garbage collected if no other part of the program is using that object, since we could always retrieve the object from permanent storage. In addition, we want to avoid using a soft reference because this puts pressure on the garbage collector (since it has to wait until running out of memory to reclaim the objects). If we use weak references, we give the garbage collector greater freedom to collect an Employee object more quickly.
This approach allows us to work with a subset of a very large
collection of objects (all employees) in a Java program running on a machine
with much less memory than we would need if we tried to read in all Employee
objects. If we didn’t have weak references, we would have to work around
the garbage collector to determine when to "free" a given Employee object,
removing all the benefits of the garbage collector and automatic memory
management.
Phantom References
Phantom references are a bit different than the previous two kinds of
references. It turns out that you can never get back the referent of a
PhantomReference once you have created it (calling the get() method always
returns null). Yet the PhantomReference still holds onto a reference to
its referent. Why is this?
Phantom references are designed to allow for "pre-mortem" cleanup. This means that you can learn about an object which is going to be garbage collected just before it actually gets collected and clean up resources it is using. This is particularly useful if you have several objects collaborating together, and you need to do the cleanup only when all of the objects are no longer using that shared resource. You can keep track of the shared resource and when the last object becomes phantomly reachable do the actual cleanup.
This still leaves one piece of the puzzle missing: how do we know when the object has become phantomly reachable? This leads us to the one remaining class in the java.lang.ref package: ReferenceQueue. When creating a reference object (phantom, weak, or soft), you can specify a reference queue to associate with the reference object. In addition to the behavior already described, the garbage collector will place such reference objects onto the specified ReferenceQueue when it takes action on that reference object.
This allows us to read the references off the queue and know that the garbage collector has done its work with that reference. In the case of a PhantomReference, we can take note of the references which have become phantom and when the reference to the last object using the shared resource "goes phantom", we can clean up that shared resource. We can choose to dedicate a thread to reading entries off a ReferenceQueue, or we can poll it at strategic points in the code.
Summary
The new kinds of references provided by the java.lang.ref package enable
developers to build smarter, more efficient programs. And while we can’t
create fundamentally new kinds of references, we can subclass the concrete
reference classes (SoftReference, WeakReference, and PhantomReference) to add
features (this is common with PhantomReference as a way to keep track of the
shared resource to be cleaned up).
These classes are not used frequently, but when they are
needed they are invaluable. By making them a standard part of Java 2[TM],
programmers get a consistent means to build more robust software without
resorting to platform/JVM-specific approaches.
OCI Educational Services
OCI has one of the most comprehensive OO training curriculums in the country. Clients contract group training that is either taught at the client site or at an OCI Education Center in Tempe, AZ or St. Louis, MO. We encourage you to check our our Object-Oriented Technology Curriculum show below: (click on course titles for online descriptions)
|
For more information or to register, email training.
Object Computing, Inc. is a Sun Authorized Java Center in St. Louis and a Member of the Object Management Group, OMG. OCI specializes in distributed computing using object-oriented and web-enabled technologies and provides Consulting, Education, and Product Development services to clients nation-wide. For more information contact us at 314-579-0066 (St. Louis), 480-752-0042 (Tempe) or email info.
For Information on Employment
Opportunities
Click here OCI
CAREER OPPORTUNITIES or email hr.
The Java News Brief is a monthly newsletter. The
purpose and intent of this publication is to advance Java, provide technical
value, and to announce available OCI Java services. If you would prefer to
not receive this newsletter or would like to subscribe please email JNB
and enter SUBSCRIBE or UNSUBSCRIBE within the Subject line.
Copyright (c) 2000. Object Computing, Inc. All rights
reserved. Java and all Java-based marks are trademarks or
registered trademarks of Sun Microsystems, Inc. in the United States and other
countries. Object Computing, Inc. is independent of Sun Microsystems, Inc.