Thursday, September 20, 2012

Eclipse IAdaptable pattern – Show Properties for Items in a View

This example shows how IAdaptable is used in Eclipse in a real example. To get a taste of how Adapter design pattern works in Eclipse, go to those posts: post1 post2.

Suppose you have created a view by using eclipse “Extension wizard”. (If you do not know this, try to play around and get this done.)


And Now change code in SampleView.java to be the following:
package adapterview.views;
 
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.*;
import org.eclipse.jface.viewers.*;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.*;
import org.eclipse.swt.SWT;
 
public class SampleView extends ViewPart {
 
 private TableViewer viewer;
 
 class ViewLabelProvider extends LabelProvider implements
   ITableLabelProvider {
  public String getColumnText(Object obj, int index) {
   TestItem testItem = (TestItem) obj;
   return testItem.getSummary();
  }
 
  public Image getColumnImage(Object obj, int index) {
   return getImage(obj);
  }
 
  public Image getImage(Object obj) {
   return PlatformUI.getWorkbench().getSharedImages()
     .getImage(ISharedImages.IMG_OBJ_ELEMENT);
  }
 }
 
 /**
  * This is a callback that will allow us to create the viewer and initialize it.
  */
 
 public void createPartControl(Composite parent) {
  viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
    | SWT.V_SCROLL);
  viewer.setContentProvider(new ArrayContentProvider());
  viewer.setLabelProvider(new ViewLabelProvider());
  getSite().setSelectionProvider(viewer);
  viewer.setInput(getElements());
 
 }
 
/**
  * Passing the focus request to the viewer's control.
  */
 
 public void setFocus() {
  viewer.getControl().setFocus();
 }
 
 // Build up a simple data model
 private TestItem[] getElements() {
  TestItem[] testItems = new TestItem[2];
  TestItem testItem = new TestItem();
  testItem.setSummary("First Item");
  testItem.setDescription("A very good description");
  testItems[0] = testItem;
  testItem = new TestItem();
  testItem.setSummary("Second Item");
  testItem.setDescription("Another very good description");
  testItems[1] = testItem;
  return testItems;
 }
}
TestItem.java
package adapterview.views;
public class TestItem {
 private String summary;
 private String description;
 public String getSummary() {
  return summary;
 }
 public void setSummary(String summary) {
  this.summary = summary;
 }
 public String getDescription() {
  return description;
 }
 public void setDescription(String description) {
  this.description = description;
 }
}
Basically, this will create a view and shown like this figure.

What if I want to show the Summary and Description in a property view when each item is clicked? You may think about changing some part of the code in the SampleView, but Eclipse platform is amazing and there is no need to change in this class.
What we need is to add an adapter for TestItem Class.
Now add the following snippet to the plugin.xml file.
<extension
         point="org.eclipse.core.runtime.adapters">
      <factory
            adaptableType="adapterview.views.TestItem"
            class="adapterplace.TestItemAdapterFactory">
         <adapter
               type="org.eclipse.ui.views.properties.IPropertySource">
         </adapter>
      </factory>
</extension>
This declares the following three classes:
1. adaptableType is TestItem
2. the factory to create adapter for adaptableType(TestItem) is TestItemAdapterFactory
3. adapter is IPropertySource which is required for property view to show properties.
Recall the apple and orange example in my previous post, now here we want to go from TestItem to IPropertySource.
File file hierarchy is like this:

TestItemAdapterFactory.java
package adapterplace;
 
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.ui.views.properties.IPropertySource;
import adapterview.views.*;
 
public class TestItemAdapterFactory implements IAdapterFactory {
 
 @Override
 public Object getAdapter(Object adaptableObject, Class adapterType) {
  if (adapterType== IPropertySource.class && adaptableObject instanceof TestItem){
   return new TestItemAdapter((TestItem) adaptableObject);
  }
  return null;
 }
 
 @Override
 public Class[] getAdapterList() {
  // TODO Auto-generated method stub
  return null;
 }
}
TestItemAdapter.java – this class wrap a TestItem object with IPropertySource’s methods, which in turned are required by Property view.
package adapterplace;
 
import adapterview.views.TestItem;
import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;
import org.eclipse.ui.views.properties.TextPropertyDescriptor;
 
 
public class TestItemAdapter implements IPropertySource {
 private final TestItem testItem;
 
 public TestItemAdapter(TestItem testItem) {
  this.testItem = testItem;
 }
 
 
 @Override
 public boolean isPropertySet(Object id) {
  return false;
 }
 
 @Override
 public Object getEditableValue() {
  return this;
 }
 
 @Override
 public IPropertyDescriptor[] getPropertyDescriptors() {
 
  return new IPropertyDescriptor[] {
    new TextPropertyDescriptor("summary", "Summary"),
    new TextPropertyDescriptor("description", "Description") };
 }
 
 @Override
 public Object getPropertyValue(Object id) {
  if (id.equals("summary")) {
   return testItem.getSummary();
  }
  if (id.equals("description")) {
   return testItem.getDescription();
  }
  return null;
 }
 
 @Override
 public void resetPropertyValue(Object id) {
 
 }
 
 @Override
 public void setPropertyValue(Object id, Object value) {
  String s = (String) value;
  if (id.equals("summary")) {
   testItem.setSummary(s);
  }
  if (id.equals("description")) {
   testItem.setDescription(s);
  }
 }
}
Result: when an item in the sample view is selected, property view shows its property.

Chain of Responsibility Design pattern

The Chain of Responsibility (CoR) pattern decouples the sender and receiver of a request by interposing a chain of objects between them.

CoR introduction

The Chain of Responsibility pattern uses a chain of objects to handle a request, which is typically an event. Objects in the chain forward the request along the chain until one of the objects handles the event. Processing stops after an event is handled.
Figure 1 illustrates how the CoR pattern processes requests.

Figure 1. The Chain of Responsibility pattern
In Design Patterns, the authors describe the Chain of Responsibility pattern like this:
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

  • You want to decouple a request's sender and receiver
  • Multiple objects, determined at runtime, are candidates to handle a request
  • You don't want to specify handlers explicitly in your code

If you use the CoR pattern, remember:
  • Only one object in the chain handles a request
  • Some requests might not get handled

Those restrictions, of course, are for a classic CoR implementation. In practice, those rules are bent; for example, servlet filters are a CoR implementation that allows multiple filters to process an HTTP request.




Adapter Design Pattern

Adapter Design Pattern:
 
Software usually consists of a mixture of in-house and purchased software that must work together to produce a seamless user interface. But disparate software packages are not aware of each other's object models, so they can't work together—without adapters. Adapters let objects from unrelated software packages collaborate by adapting one interface to another. Learn how the Adapter design pattern can save you a lot of time and effort by combining disparate software systems.

The Adapter pattern lets disparate object types work together.

Introducing Adapter

Adapters are necessary because dissimilar elements need to interoperate. From wrenches to computer networks, physical adapters are abundant. In software, adapters make dissimilar software packages work together; for example, you might have a tree of objects (call them Nodes) you want to display using Swing's JTree. The JTree class can't display your Nodes directly, but it can display TreeNode instances. With an adapter, you can map your Nodes to TreeNodes. Because Swing trees use the Adapter pattern, you can display any kind of tree—from Document Object Model (DOM) to Swing component hierarchies to a compiler parse tree—just by implementing a simple adapter.


In Design Patterns, the authors describe the Adapter pattern like this:
Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
Figures 2 and 3 show the Adapter pattern's two standard variations.

Figure 2. Adapter with inheritance. Click on thumbnail to view full-size image.


Figure 3. Adapter with delegation. Click on thumbnail to view full-size image.

Adapters masquerade as one type of object by implementing its interface; they inherit (or delegate) functionality from another class. That way, you can effectively substitute objects (known as Adaptees) for target (Target) objects. For the JTree in Figure 1, I adapt the objects in the tree (UIComponents) to Swing, so a JTree instance can manipulate them. Considering the amount of code that sits behind JTree, this simple adapter provides a huge return on investment. Let's see how it works.

In Eclipse:

This pattern is used a lot in Eclipse, allowing plug-ins to be loosely coupled, yet still be integrated into the Eclipse runtime.


Adapters in the Real World 

A real world analogy always helps with the understanding of a design pattern. The best example for the adapter pattern is based around AC power adapters. Say you're visiting Europe from the US, with your laptop, which expects a US power supply. To get your laptop plugged in, you're going to need to get a power adapter that accepts your US plug and allows it to plug in to the European power outlet. The AC adapter knows how to deal with both sides, acting as a middleman - this is the adapter pattern.

The Adapter Pattern

The Adapter is known as a structural pattern, as it's used to identifying a simple way to realize relationships between entities. The definition of Adapter provided in the original Gang of Four book on Design Patterns states: 
Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
Let's take a look at the classic diagram definition of  the adapter pattern:

The Target interface defines the domain specific interface that the Client used, so the client collaborates with objects that implement the Target interface. On the other side of things, the Adaptee is the existing interface that needs adapting in order for our client to interact with it. The Adapter adapts the Adaptee to the Target interface - in other words, it translates the request from the client to the adaptee.


Let's take a look at the interactions in a sequence diagram: 

In this example, as far as the Client is concerned it's just calling the request method of the Target interface, which the Adapter has implemented. In the background however, the Adapter knows that to return the right result, it needs to call a different method, specificAdapteeRequest, on the Adaptee.
Note: the pattern described here is the object adapter. There is a class adapter pattern, but you need multiple inheritance to use it. Seeing as Java doesn't support multiple inheritance, I'm going to leave this out.

Where Would I Use This Pattern?

The main use of this pattern is when a class that you need to use doesn't meet the requirements of an interface. As mentioned before, adapters are common across Eclipse plug-ins. For a particular object to contribute to the Properties view, adapters are used display the objects data. The view itself doesn't need to know anything about the object the it is displaying properties for. 

Where Would I Use This Pattern?

The main use of this pattern is when a class that you need to use doesn't meet the requirements of an interface. As mentioned before, adapters are common across Eclipse plug-ins. For a particular object to contribute to the Properties view, adapters are used display the objects data. The view itself doesn't need to know anything about the object the it is displaying properties for. 

So How Does It Work In Java?

The following example shows a simple implementation of the pattern. Consider that we have a third party library that provides sorting functionality through it's NumberSorter class. This is our Adaptee.
01./*
02.* This is our adaptee, a third party implementation of a
03.* number sorter that deals with Lists, not arrays.
04.*/
05.public class NumberSorter
06.{
07.public List<Integer> sort(List<Integer> numbers)
08.{
09.//sort and return
10.return new ArrayList<Integer>();
11.}
12. 
13.}
Our Client deals with primitive arrays rather than Lists. For the sake of this example, lets say we can't change the client to use Lists. 
1.int[] numbers = new int[]{34, 2, 4, 12, 1};
2. 
3.Sorter sorter = new SortListAdapter();
4.sorter.sort(numbers);
We've provided a Sorter interface that expects the client input. This is our target.
1.//this is our Target interface
2.public interface Sorter
3.{
4.public int[] sort(int[] numbers);
5.}
Finally, the SortListAdapter implements our target interface and deals with our adaptee, NumberSorter

01.public class SortListAdapter implements Sorter
02.{
03. 
04.@Override
05.public int[] sort(int[] numbers)
06.{
07.//convert the array to a List
08.List<Integer> numberList = new ArrayList<Integer>();
09. 
10.//call the adapter
11.NumberSorter sorter = new NumberSorter();
12.numberList = sorter.sort(numberList);
13. 
14.//convert the list back to an array and return
15. 
16.return sortedNumbers;
17.}
18. 
19.}
While this example may be overkill, it illustrates how the adapter pattern can work.

Watch Out for the Downsides

Some say that the Adapter pattern is just a fix for a badly designed system, which didn't consider all possibilties. While this is a fair point, it is an important part of a pluggable architecture.  It can also add a level of complexity to your code, making debugging more difficult.



Wednesday, September 19, 2012

Comparable and Comparator in Java


Employee record with Department, Emp Name and Emp Id:

Original Data:

BI :Kondal :109
HANA :Ban :103
HANA :Anand :115
ERP :Can :102
CRM :Yangi :100
BI :Damn :114

Required Format: Display the emp names in sorted way based on the department name.

BI :Damn :114
BI :Kondal :109
CRM :Yangi :100
ERP :Can :102
HANA :Anand :115
HANA :Ban :103

We can acheive this in two different ways.
1.  By implementing comparable interface in Employee class.
 - Override compareTo method
 - Invoke Collections.sort(arraylist);

2. By implementing comparator interface, as specified below without even touching the employee class
- Override compare method
- Invoke Collections.sort(arraylist, new EmployeeComparator());

Employee class

public
class Employee /* implements Comparable<Employee>*/ {
private int empId;
private String empName;
private String department;

public Employee(int empId, String empName, String department) {
this.empId = empId;
this.empName = empName;
this.department = department;
}
public void setEmpId(int empId) {
this.empId = empId;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public int getEmpId() {
return empId;
}
public String getEmpName() {
return empName;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
/* @Override
public int compareTo(Employee o) {
if (this.getDepartment().compareTo(o.getDepartment()) == 0) {
return this.getEmpName().compareTo(o.getEmpName());
}
return this.getDepartment().compareTo(o.getDepartment());
}*/
}
 
EmployeeComparator class

import
java.util.Comparator;
 
public
class EmployeeComparator implements Comparator<Employee>{
@Override
public
int compare(Employee e1, Employee e2) {
if
(e1.getDepartment().compareTo(e2.getDepartment()) == 0) {
return
e1.getEmpName().compareTo(e2.getEmpName());
}
return
e1.getDepartment().compareTo(e2.getDepartment());
}
}

EmployeProfiles class

import
java.util.ArrayList;
import
java.util.Collections;

public
class EmployeProfiles {
public
static void main(String[] args) {
ArrayList<Employee> empList = new
ArrayList<Employee>();
empList.add(new
Employee(109, "Kondal", "BI"));
empList.add(new
Employee(103, "Ban", "HANA"));
empList.add(new
Employee(115, "Anand", "HANA"));
empList.add(new
Employee(102, "Can", "ERP"));
empList.add(new
Employee(100, "Yangi", "CRM"));
empList.add(new
Employee(114, "Damn", "BI"));
// Natural order in the array list
for
(Employee employee : empList) {
System.out
.println(employee.getDepartment() + " :"
+ employee.getEmpName() + " :" + employee.getEmpId());
}
// Apply sorting
Collections.sort(empList, new
EmployeeComparator());
System.out
.println("------------");
// sorted list
for
(Employee employee : empList) {
System.out
.println(employee.getDepartment() + " :"
+ employee.getEmpName() + " :" + employee.getEmpId());
}
}
}

Reference Objects and Garbage Collection

Article reference: http://pawlan.com/monica/articles/refobjs/

Reference Objects and Garbage Collection

Important Notes:

The reference in a reference object is treated specially by the garbage collector. A reference object encapsulates a reference to some other object, which is called the referent.

When an object is reachable from the root set by some chain of ordinary references (no reference objects involved), that object is said to be strongly reachable.

 If, however, the only ways to reach an object involve at least one weak reference object, the object
is said to be weakly reachable

The SoftReference, WeakReference, and PhantomReference classes define three kinds of reference objects and three strengths of object reachability. From strongest to weakest, the strengths of reachability are the following:
•Strongly reachable
•Softly rechable
•Weakly reachable
•Phantomly reachable
•Unreachable


An object is softly reachable if it is not strongly reachable and there is a path to it with no weak or phantom references, but one or more soft references. The garbage collector might or might not reclaim a softly reachable object depending on how recently the object was created or accessed, but is required to clear all soft references before throwing an OutOfMemoryError.

A java.lang.ref.ReferenceQueue is a simple data structure onto which the garbage collector places reference objects when the reference field is cleared (set to null). You would use a reference queue to find out when an object becomes softly, weakly, or phantomly reachable so your program can take some action based on that knowledge. For example, a program might perform some post-finalization cleanup processing that requires an object to be unreachable (such as the deallocation of resources outside the Java heap) upon learning that an object has become phantomly reachable

An object is weakly reachable when the garbage collector finds no strong or soft references, but at least one path to the object with a weak reference. Weakly reachable objects are finalized some time after their weak references have been cleared. The only real difference between a soft reference and a weak reference is that the garbage collector uses algorithms to decide whether or not to reclaim a softly reachable object, but always reclaims a weakly reachable object

An object is phantomly reachable when the garbage collector finds no strong, soft, or weak references, but at least one path to the object with a phantom reference. Phantomly reachable objects are objects that have been finalized, but not reclaimed

The garbage collector processes reference objects in order from strongest to weakest. The processing always happens in the following order, but there is no guarantee when the processing will occur:
•Soft references
•Weak references
•Finalization
•Phantom references
•Reclamation


A WeakHashMap object is like a HashMap object in that it stores key-value pairs where the key is an arbitrary object. But, in a WeakHashMap object, the key is referenced by a weak reference object internal to the WeakHashMap object



The Reference Object application programming interface (API) is new in the Java Development Kit (JDK) 1.2. This API allows a program to maintain special references to objects that allow the program to interact with the garbage collector in limited ways. Not all programs require this level of interaction with the garbage collector. For example, a program that keeps a lot of objects in memory or a program that needs to perform cleanup operations on related objects before an object is reclaimed might be good candidates for using the Reference Objects API.
  • A web-based program might display a lot of images when an end user goes to a particular page on the web. If the end user leaves the page, it is not always certain he or she will return. Such a program can use reference objects to create a situation where the garbage collector reclaims the images when heap memory runs low. In the event the end user returns to the page, the program can reload the image if it has been reclaimed.
  • A program can use a reference queue to create a situation where the program is notified when a certain object is reachable only through reference objects. Upon notification, the program can proceed with clean-up operations on other related objects to make them eligible for garbage collection at the same time.
Because it is essential to understand garbage collection before you can understand how reference objects work, this article begins by describing how garbage collection works when no reference objects are involved, followed by a discussion of how things change when reference objects are added to the heap.

Vanilla Garbage Collection

The garbage collector's job is to identify objects that are no longer in use and reclaim the memory. What does it mean for an object to be in use?
Note: An object is in use if it can be accessed or reached by the program in its current state.
An executing Java program consists of a set of threads, each of which is actively executing a set of methods (one having called the next). Each of these methods can have arguments or local variables that are references to objects. These references are said to belong to a root set of references that are immediately accessible to the program. Other references in the root set include static reference variables defined in loaded classes, and references registered through the Java Native Interface (JNI) API.
All objects referenced by this root set of references are said to be reachable by the program in its current state and must not be collected. Also, those objects might contain references to still other objects, which are also reachable, and so on.
All other objects on the heap are considered unreachable, and all unreachable objects are eligible for garbage collection. If an unreachable object has a finalize() method, arrangements are made for the object's finalizer to be called. Unreachable objects with no finalizers and objects whose finalizers have been called are simply reclaimed during garbage collection.
Garbage collection algorithms vary, but they all have in common the task of identifying the objects that are reachable from the root set and reclaiming the space occupied by any other objects.
In the diagram, which is a simplified view of the stack and heap for instructional purposes, objects inside the blue square are reachable from the thread root set, while objects outside the square (in red) are not.
Reachable and
unreachable objects from the thread root set.
Fig. 1: How garbage collection works.
An object may refer to reachable objects and still be unreachable itself. Likewise, an object can be unreachable in spite of references to it, if those references are all from unreachable objects.
Conservative Garbage Collection: If you use the Java Native Interface (JNI) API to make C calls, the garbage collector might see something in memory created by the C code that looks like a pointer, but is actually garbage. In this case, the memory is not garbage collected because the Java VM is conservative and does not reclaim memory that looks like it could be allocated to a pointer.

What Happens When You Use Reference Objects

How does the introduction of reference objects change things? Unlike ordinary references, the reference in a reference object is treated specially by the garbage collector. A reference object encapsulates a reference to some other object, which is called the referent.
The referent of a reference object is specified when the reference object is created. In the following code, image is an image object passed to sr, a SoftReference object. The image object is the referent of sr, and the reference field in sr is a soft reference to image.
  Image image = (
    sr == null) ? null : (Image)(sr.get());
  if (image == null) {
    image = getImage(getCodeBase(), "truck1.gif");
    sr = new SoftReference(image);
  }

Object Reachability

Besides strongly reachable and unreachable objects, the Reference Objects API gives you strengths of object reachability. You can have softly, weakly and phantomly reachable objects and gain a limited amount of interaction with the garbage collector according to the strength of the object's reachability.
The next sections explain these strengths and how to use them. This section takes a look at how garbage collection is changed when two of the objects on the heap in Figure 1 are changed to weak reference objects.
When an object is reachable from the root set by some chain of ordinary references (no reference objects involved), that object is said to be strongly reachable. If, however, the only ways to reach an object involve at least one weak reference object, the object is said to be weakly reachable. An object is considered by the garbage collector to be in use if it is strongly reachable. Weakly reachable objects, like unreachable objects, are eligible for collection.
So, weak references allow you to refer to an object without keeping it from being collected. If the garbage collector collects a weakly reachable object, all weak references to it are set to null so the object can no longer be accessed through the weak reference.
Weakly reachable
objects
Fig. 2: Adding reference objects to the heap.
  • Unreachable objects (outside the strongly and weakly reachable areas) are not reachable from the root set.
  • Strongly reachable objects (inside the strongly reachable area to the lower left) are reachable through at least one path that does not go through a reference object.
  • Weakly reachable objects (inside the weakly reachable area shown enclosed with a dashed line to the upper-right) are not strongly reachable through any path, but reachable through at least one path that goes through a weak reference.
The diagram above shows two paths to the object on the heap with the X. It can be reached through the weak reference, and directly from the stack without going through a weak reference object. The object with the X is strongly reachable and not weakly reachable because one path leads to it from the root set without going through a reference object. The garbage collection behavior for this object is the same as other strongly reachable objects until it is no longer reachable from the root set, at which time it becomes weakly reachable.
Here is another way to look at the same idea:
Two paths to the
same object, weakly reachable and strongly reachable.
Fig. 3: References suspended from a beam.
Imagine the root set of references as a solid beam from which objects are suspended by cables (strong references). An object might contain references to other objects. Weak reference objects connect to their referent not by a cable, but by a flexible rubber band, no number of which could support an object. Objects not held by cables fall into the garbage bin below.
The Reference Objects API provides several types of reference objects, which gives a program several strengths of object reachability once the referent is no longer strongly reachable. The next section explains the different types of reference objects and what is meant by strengths of reachability.

All About Reference Objects

The Reference Objects API consists of the classes listed below and shown in the figure.
Reference
objects API classes.
Fig. 4: Class hierarchy diagram.
The SoftReference, WeakReference, and PhantomReference classes define three kinds of reference objects and three strengths of object reachability. From strongest to weakest, the strengths of reachability are the following:
  • Strongly reachable
  • Softly rechable
  • Weakly reachable
  • Phantomly reachable
  • Unreachable
See the >JDK 1.2 API specification for the class and method descriptions:

Strengths of Reachability

The Reference Objects API defines strengths of object reachability. You can have (going from strongest to weakest) softly, weakly and phantomly reachable objects and gain an amount of interaction with the garbage collector according to the strength of an object's reachability.
There is no limit to the number or type of references there can be to an object. One object can be referenced by any mix of strong, soft, weak, and phantom references depending on your application requirements.
To determine an object's strength of reachability, the garbage collector starts at the root set and traces all the paths to objects on the heap. The reference objects that the garbage collector goes through to reach an object are what determine the reachability of that object. When any path to an object is free of reference objects, the object is strongly reachable. When all paths have one or more reference objects, the object is softly, weakly, or phantomly reachable according to the type of reference object(s) the garbage collector finds. In general, an object is only as reachable as the weakest link in the strongest path from the root set. The sections to follow describe how this all works.

Softly Reachable

An object is softly reachable if it is not strongly reachable and there is a path to it with no weak or phantom references, but one or more soft references. The garbage collector might or might not reclaim a softly reachable object depending on how recently the object was created or accessed, but is required to clear all soft references before throwing an OutOfMemoryError.
If heap memory is running low, the garbage collector may, at its own discretion, find softly reachable objects that have not been accessed in the longest time and clear them (set their reference field to null).
SoftReference objects work well in applications that, for example, put a large number of images into memory and there is no way to know if the application (driven by end user input) will access a given image again. If the garbage collector reclaims an image that has not been accessed for a long time, and the application needs to access it again, the application reloads the image and displays it.

Using Soft References in Web-Based Programs

Soft references are very useful in web-based programs where, for example, an applet creates an image to display on a web page. When the user opens the web page, the applet code gets the image and displays it. If the code also creates a soft reference to the image, the garbage collector has the option to reclaim or not reclaim the memory allocated to the image when the user moves to another web page. Here is how the example application looks in memory:
Softly reachable
Fig. 5: Using soft references.
If the user returns to the web page where the image is, the applet code uses the SoftReference.get method to check the soft reference to find out if the image is still in memory. If the image has not been reclaimed by the garbage collector, it is quickly displayed on the page; and if the image has been reclaimed, the applet code gets it again.
If your program calls the SoftReference.clear method, the reference may become eligible for reclamation. However, if there is a strong reference to the object, calling the clear method does not cause the garbage collector to reclaim the object. In this case, the soft reference is null, but garbage collection does not happen until the object is no longer strongly reachable.
Here is the complete DisplayImage.java source code.
NOTE: The im object is set to null because there is no guarantee the stack slot occupied by it will be cleared when it goes out of scope. A later method invocation whose stack frame contains the slot previously occupied by im might not put a new value there, in which case, the garbage collector still considers the slot to contain a root.
This is a problem even with nonconservative exact collectors. As a precaution, you can increase the probability that an object will become softly, weakly, finalizable, or phantomly reachable by clearing variables that refer to it.
import java.awt.Graphics;
import java.awt.Image;
import java.applet.Applet;
import java.lang.ref.SoftReference;

public class DisplayImage extends Applet {

        SoftReference sr = null;

        public void init() {
            System.out.println("Initializing");
        }

        public void paint(Graphics g) {
            Image im = (
              sr == null) ? null : (Image)(
              sr.get());
            if (im == null) {
                System.out.println(
                "Fetching image");
                im = getImage(getCodeBase(),
                   "truck1.gif");
                sr = new SoftReference(im);
           }
           System.out.println("Painting");
           g.drawImage(im, 25, 25, this);
           im = null;  
        /* Clear the strong reference to the image */
        }

        public void start() {
            System.out.println("Starting");
        }

        public void stop() {
            System.out.println("Stopping");
        }

}

Reference Queues

A java.lang.ref.ReferenceQueue is a simple data structure onto which the garbage collector places reference objects when the reference field is cleared (set to null). You would use a reference queue to find out when an object becomes softly, weakly, or phantomly reachable so your program can take some action based on that knowledge. For example, a program might perform some post-finalization cleanup processing that requires an object to be unreachable (such as the deallocation of resources outside the Java heap) upon learning that an object has become phantomly reachable.
To be placed on a reference queue, a reference object must be created with a reference queue. Soft and weak reference objects can be created with a reference queue or not, but phantom reference objects must be created with a reference queue:
ReferenceQueue queue = new ReferenceQueue();
  PhantomReference pr = 
    new PhantomReference(object, queue);
Another approach to the soft reference example from the diagram on the previous page could be to create the SoftReference objects with a reference queue, and poll the queue to find out when an image has been reclaimed (its reference field cleared). At that point, the program can remove the corresponding entry from the hash map, and thereby, allow the associated string to be garbage collected.
Note: A program can also wait indefinitely on a reference queue with the remove() method, or for a bounded amount of time with the remove(long timeout) method.
Soft and weak reference objects are placed in their reference queue some time after they are cleared (their reference field is set to null). Phantom reference objects are placed in their reference queue after they become phantomly reachable, but before their reference field is cleared. This is so a program can perform post-finalization cleanup and clear the phantom reference upon completion of the cleanup.

Weakly Reachable

An object is weakly reachable when the garbage collector finds no strong or soft references, but at least one path to the object with a weak reference. Weakly reachable objects are finalized some time after their weak references have been cleared. The only real difference between a soft reference and a weak reference is that the garbage collector uses algorithms to decide whether or not to reclaim a softly reachable object, but always reclaims a weakly reachable object.
Weak references work well in applications that need to, for example, associate extra data with an unchangeable object, such as a thread the application did not create. If you make a weak reference to the thread with a reference queue, your program can be notified when the thread is no longer strongly reachable. Upon receiving this notification, the program can perform any required cleanup of the associated data object.
To make the Thread object weakly reachable, its strong reference must be set to null. After the garbage collector clears the weak reference to the thread, it places the weak reference on the queue. When the program removes the reference from the queue, it can then remove the corresponding hash map entry, and thereby, allow the data object to be reclaimed.
Weakly reachable
Fig. 6: Using weak references.
The following code examples stores an object and some extra data in a hash map. The object is referenced by a weak reference object that was created with a reference queue. This is a very simple code example to illustrate the points discussed in this article. In a real application, the data would be associated with the object well after the object is created; otherwise, you could keep the data in a subclass of the object instead of using a weak reference.
After the object becomes weakly reachable, the garbage collector clears the weak reference and places it in the reference queue. The code queries the reference queue for the weak reference, and upon finding the weak reference there, sets the reference to the extra data to null so the extra data is garbage-collected after the object is.
An important point in this example is that the object can be reached from the stack through two paths: one path goes through the weak reference and the other goes through the hash map. The object does not become weakly reachable until the reference to it in the hash map is null. It is not enough to just set the object to null.
import java.lang.ref.*;
import java.util.*;

public class WeakObj {

 public static void main(String[] args) {
  try {
    ReferenceQueue aReferenceQueue 
      = new ReferenceQueue();
    Object anObject = new Object();
    WeakReference ref = new WeakReference(anObject,
                                 aReferenceQueue);
    String extraData = new String("Extra Data");
    HashMap aHashMap = new HashMap();;

//Associate extraData (value) with weak reference
// (key) in aHashMap
    aHashMap.put(ref, extraData);

//Check that a reference to an object was created
    System.out.println(
      "*** created ref to some object");
    System.out.println();
    System.out.println(
      "contents of ref: " + ref.get());
    System.out.println();


//Check whether the Reference Object is enqueued
    System.out.println(
      "ref.isEnqueued(): " + ref.isEnqueued());
    System.out.println();

//Clear the strong reference to anObject
    anObject = null;

//Clear the strong reference to extraData
    if(anObject == null){
      extraData = null;
    }
//Run the garbage collector, and
//Check the reference object's referent
    System.out.println("*** running gc...");
    System.gc();
    System.out.println();
    System.out.println(
      "contents of ref: " + ref.get());
    System.out.println();


//Check whether the reference object is enqueued
    System.out.println(
      "ref.isEnqueued(): " + ref.isEnqueued());
    System.out.println();

//Enqueue the reference object. 
//This method returns false
//if the reference object is already enqueued.
    System.out.println("enqueued="+ref.enqueue());

  } catch (Exception e) {
    System.err.println("An exception occurred:");
    e.printStackTrace();
  }
 }
}

Phantomly Reachable

An object is phantomly reachable when the garbage collector finds no strong, soft, or weak references, but at least one path to the object with a phantom reference. Phantomly reachable objects are objects that have been finalized, but not reclaimed.
When the garbage collector finds only phantom references to an object, it enqueues the phantom reference. The program polls the reference queue and upon notification that the phantom reference is enqueued, performs post-finalization cleanup processing that requires the object to be unreachable (such as the deallocation of resources outside the Java heap). At the end of the post-finalization cleanup code, the program should call the clear() method on the phantom reference object to set the reference field to null to make the referent eligible for garbage collection.

Chains of reference objects

A given path to an object can contain more than one kind of reference object, which creates a chain of reference objects. The garbage collector processes reference objects in order from strongest to weakest. The processing always happens in the following order, but there is no guarantee when the processing will occur:
  • Soft references
  • Weak references
  • Finalization
  • Phantom references
  • Reclamation
In the diagram below, there is a chain of reference objects to Some Object. When the garbage collector processes the reference objects, will it find Some Object to be phantomly, weakly, or softly reachable?
Chain of reference
objects.
Fig. 7: How reachable is some object?
The answer is Some object is phantomly reachable. In general an object is only as reachable as the weakest link in the strongest path from a root set. In the diagram, the phantom reference is strongly reachable, but all other objects are phantomly reachable.
However, if the weak reference is strongly reachable as shown in the next diagram, both Phantom and Weak reference are strongly reachable, and Soft reference and Some object are weakly reachable.
Chain with phantom,
weak, and soft references.
Fig. 8: Phantomly or weakly reachable?
Can you guess what happens if Soft reference is strongly reachable?
What happens
when a soft reference is strongly reachable?
Fig. 9: Phantomly, weakly, or softly reachable?
The answer is Phantom, Weak, and Soft reference are strongly reachable, and Some Object is softly reachable.

WeakHashMap Class

A WeakHashMap object is like a HashMap object in that it stores key-value pairs where the key is an arbitrary object. But, in a WeakHashMap object, the key is referenced by a weak reference object internal to the WeakHashMap object.
After the object referenced by the weak key becomes weakly reachable, the garbage collector clears the internal weak reference. At this point, the key and its associated value become eligible for finalization, and if there are no phantom references to the key, the key and value then become eligible for reclamation. The WeakHashMap class provides a weak hash table facility, but in a class that fits into the new Collections framework.
If you use a WeakHashMap object instead of the HashMap and WeakReference objects, you can associate pairs of objects as keys and values. The value is made eligible for garbage collection when the key becomes weakly reachable. This uses fewer lines of code because you do not need a WeakReference object, and you do not have to explicitly set the associated object to null.

Conclusion

If you have ever wanted the garbage collector to reclaim unused objects when heap memory is running low, or a convenient way to be sure an object is collected when an object it is related to is no longer in use, the JDK 1.2 Reference Objects API is for you. Not only do you get some control over garbage collection, but your programs will run better too.
© 1994-2005 Sun Microsystems, Inc.