Login With Github

Do You Really Know the 4 Reference Types in Java?

There are four levels of references provided in Java: SoftReference, FinalReference, WeakReference, and PhantomReference. Among the four reference types, only the FinalReference class is visible in the package, and the other three reference types are all public and can be used directly in the application. The class structure of the reference type is shown in the figure.

1. FinalReference

References in Java are similar to the pointers in C. And you can operate on the objects in the heap through references. Here is an example:

StringBuffer stringBuffer = new StringBuffer("Helloword");

The variable str points to the heap space where the StringBuffer instance is located, and you can manipulate the object with str.

Here are the features of FinalReferences:

  1. FinalReferences provide direct access to the target objects.
  2. Objects pointed to by FinalReferences won't be reclaimed by the system at any time. JVM pefers to throw an OOM exception rather than reclaim the object pointed to by the FinalReference.
  3. FinalReferences may cause memory leaks.

2. SoftReference

SoftReference are the strongest reference types except FinalReference. SoftReferences can be used via java.lang.ref.SoftReference. An object holding a SoftReference won't be reclaimed quickly by the JVM. JVM will determine when to recycle based on the current heap usage. Only when the heap usage is near the threshold, the SoftReferenced object will be collected. Therefore, SoftReference can be used to implement a memory-sensitive cache.

SoftReference is characterized by an instance that it can hold a soft reference to a Java object. The existence of the soft reference does not prevent the garbage collection thread from reclaiming the Java objects. It means that once the SoftReference has saved a soft reference to a Java object, the get() method provided by the SoftReference class will return a strong reference to the Java object before the GC thread reclaims the Java object. Once the GC thread reclaims the Java object, the get() method will return null.

The following is an example of how to use SoftReferences.

Set the parameter -Xmx2m -Xms2m in your IDE, and specify the heap memory size as 2m.

@Test
public void test3(){
	MyObject obj = new myObject();
	SoftReference sf = new SoftReference<>(obj);
	obj = null;
	System.gc();
//        byte[] bytes = new byte[1024*100];
//        System.gc();
	System.out.println("Is Collected: "+sf.get());
}

The result is as follows:

Is Collected: cn.zyzpp.MyObject@42110406

Open the commented statement new byte[1024*100] , which requests a large block of heap space, making a tense use of the heap memory. Call the GC again explicitly, the result is as follows:

Is Collected: null

Note that in the case of system memory shortages, SoftReferences will be recycled.

3. WeakReference

WeakReference is a type of reference that is weaker than SoftReference. In the GC system, whenever a weak reference is found, the object will be recycled regardless of whether the system heap space is sufficient. And you can use the java.lang.ref.WeakReference instance to hold a weak reference to a Java object.

public void test3(){
	MyObject obj = new MyObject();
	WeakReference sf = new WeakReference(obj);
	obj = null;
	System.out.println("Is Collected: "+sf.get());
	System.gc();
	System.out.println("Is Collected: "+sf.get());
}

The result is as follows:

Is Collected: cn.zyzpp.MyObject@42110406
Is Collected: null

SoftReference and WeakReference are very suit for being used to hold cached data that is optional. If you use them, when the system is out of memory, the cached data will be reclaimed without causing memory overflow. When the memory resources are sufficient, the cached data can exist for a long time, which will accelerate the system.

4. PhantomReference

PhantomReference is the weakest of all types. An object holding a PhantomReference is almost identical to having no reference and can be recycled by the garbage collector at any time. When trying to get a strong reference through the get() method of PhantomReferences, it will always fail. And PhantomReferences must be used with reference queues to track the garbage collection process.

When the garbage collector is going to recycle an object, if it finds that there has a PhantomReference, it will destroy the object after garbage collection and add the PhantomReference to the reference queue. According to the judging whether a PhantomReference has been added to the reference queue, the program can determine whether the referenced object is needed to be garbage collected. If the program finds that a PhantomReference has been added to the reference queue, then the necessary action will be taken before the memory of the referenced object is recycled.

public void test3(){
	MyObject obj = new MyObject();
	ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
	PhantomReference sf = new PhantomReference<>(obj,referenceQueue);
	obj = null;
	System.out.println("Is Collected: "+sf.get());
	System.gc();
	System.out.println("Is Collected: "+sf.get());
}

The result is as follows:

Is Collected: null
Is Collected: null

The get() operation on the PhantomReference always returns null because the implementation of the sf.get() method is as follows:

public T get() {
	return null;
}

5.WeakHashMap class and Its Implementation

The WeakHashMap class is in the java.util package. It implements the Map interface and is an implementation of HashMap. It uses WeakReferences as a storage scheme for internal data. WeakHashMap is a typical application of weak references, which can be used as a simple cache table solution.

The following two pieces of code use WeakHashMap and HashMap to save a lot of data respectively:

@Test
public void test4(){
	Map map;
	map = new WeakHashMap<String,Object>();
	for (int i =0;i<10000;i++){
		map.put("key"+i,new byte[i]);
	}
//        map = new HashMap<String,Object>();
//        for (int i =0;i<10000;i++){
//            map.put("key"+i,new byte[i]);
//        }
}

It uses -Xmx2M to limit the heap memory. The code that uses WeakHashMap ends running, and the code segment that uses HashMap throws exceptions.

java.lang.OutOfMemoryError: Java heap space

It can be seen that WeakHashMap will use WeakReferences when there is memory stress in the system, and release the memory data automatically which is holding WeakReferences.

However, if the keys of WeakHashMap all hold FinalReferences in the system, WeakHashMap will degenerate into a normal HashMap, because all the items cannot be cleaned up automatically.

0 Comment

temp