Java WeakReference Tutorial with Examples
1. WeakReference
No ADS
java.lang.ref.WeakReference class is used to create an object that wraps another object - innerObject. The object it wraps can be removed from memory by Garbage Collector (GC) if it is no longer being used somewhere else stronger than GC.
AnyObject.java
package org.o7planning.beans;
public class AnyObject {
private String val;
public AnyObject(String val) {
this.val = val;
}
public String getVal() {
return this.val;
}
}
For easy understanding, see the code below:
AnyObject innerObject = new AnyObject("Obj1");
WeakReference weakRef = new WeakReference(innerObject);
In the above code we have innerObject object, which is used as a parameter to create weakRef object, or in other words innerObject is being used by weakRef.
In common sense, if an object is in use somewhere, it is useful and cannot be removed from memory. However, WeakReference is a special class, which is considered weaker than Garbage Collector (GC). Object wrapped in a WeakReference can still be removed from memory by GC if it is no longer being used somewhere else stronger than GC.
WeakReference_obj_ex1.java
package org.o7planning.weakreference.ex;
import java.lang.ref.WeakReference;
import org.o7planning.beans.AnyObject;
public class WeakReference_obj_ex1 {
public static void main(String[] args) throws InterruptedException {
// Create innerObject reference points to AnyObject("Obj1").
AnyObject innerObject = new AnyObject("Obj1");
// Create WeakReference object using innerObject reference.
WeakReference<AnyObject> weakRef = new WeakReference<AnyObject>(innerObject);
System.out.println("weakRef.get(): " + weakRef.get());
// Set innerObject reference to null (Points to null).
innerObject = null;
System.out.println("\nCall System.gc().\n");
System.gc();
Thread.sleep(3000);
System.out.println("weakRef.get(): " + weakRef.get());
}
}
Output:
weakRef.get(): org.o7planning.beans.AnyObject@5e91993f
Call System.gc().
weakRef.get(): null
In the above example we call System.gc() method to tell Garbage Collector to work. This request has no immediate effect. Basically, GC is a sophisticated and complex machine that works automatically and you can only interfere with it in a limited way.
In the next example, we won't actively call System.gc() method, but GC will still remove the object wrapped inside WeakReference after a while if it's no longer being used somewhere else stronger than GC.
WeakReference_obj_ex2.java
package org.o7planning.weakreference.ex;
import java.lang.ref.WeakReference;
import org.o7planning.beans.AnyObject;
public class WeakReference_obj_ex2 {
public static void main(String[] args) throws InterruptedException {
// Create innerObject reference points to AnyObject("Obj1").
AnyObject innerObject = new AnyObject("Obj1");
// Create WeakReference object using innerObject reference.
WeakReference<AnyObject> weakRef = new WeakReference<AnyObject>(innerObject);
System.out.println("weakRef.get(): " + weakRef.get());
int i = 0;
while(true) {
AnyObject innerObj = weakRef.get();
if(innerObj == null) {
System.out.println("Inner object is removed by Garbage Collector");
System.out.println("weakRef.get(): " + innerObj);
break;
}
i++;
System.out.println(i+ " weakRef.get(): " + innerObj);
}
}
}
Output:
weakRef.get(): org.o7planning.beans.AnyObject@5e91993f
1 weakRef.get(): org.o7planning.beans.AnyObject@5e91993f
2 weakRef.get(): org.o7planning.beans.AnyObject@5e91993f
.....
283516 weakRef.get(): org.o7planning.beans.AnyObject@5e91993f
283517 weakRef.get(): org.o7planning.beans.AnyObject@5e91993f
283518 weakRef.get(): org.o7planning.beans.AnyObject@5e91993f
Inner object is removed by Garbage Collector
weakRef.get(): null
WeakReference constructors
WeakReference(T referent)
WeakReference(T referent, ReferenceQueue<? super T> q)
All methods of WeakReference are inherited from parent class.
// Methods inherited from parent.
public T get()
public void clear()
public boolean isEnqueued()
public boolean enqueue()
2. Primitive Inner Object
A primitive value is not a reference although it can be written like a reference. So if it is wrapped inside a WeakReference it will not be removed from memory by GC.
Integer innerObj1 = 1000;
Double innerObj2 = 2000.2;
String innerObj3 = "SomeString";
Example:
WeakReference_primitive_ex1.java
package org.o7planning.weakreference.ex;
import java.lang.ref.WeakReference;
public class WeakReference_primitive_ex1 {
public static void main(String[] args) throws InterruptedException {
Integer innerObj1 = 100;
String innerObj2 = "SomeString";
WeakReference<Integer> weakRef1 = new WeakReference<Integer>(innerObj1);
WeakReference<String> weakRef2 = new WeakReference<String>(innerObj2);
System.out.println("weakRef1.get(): " + weakRef1.get());
System.out.println("weakRef2.get(): " + weakRef2.get());
// Points to null.
innerObj1 = null;
innerObj2 = null;
System.out.println("\n--- Call System.gc(): ---\n");
// Call GC:
System.gc();
Thread.sleep(3000);
System.out.println("weakRef1.get(): " + weakRef1.get());
System.out.println("weakRef2.get(): " + weakRef2.get());
}
}
Output:
weakRef1.get(): 100
weakRef2.get(): SomeString
--- Call System.gc(): ---
weakRef1.get(): 100
weakRef2.get(): SomeString
3. Non-Primitive Inner Object
If an object is created by the "new" operator and wrapped inside a WeakReference, it will be removed from memory by GC if it is no longer being used somewhere else stronger than GC.
AnyObject innerObj1 = new AnyObject("Obj1");
String innerObj2 = new String("Obj2");
Integer innerObj3 = new Integer(1000);
String innerObj4 = new String("Obj4");
WeakReference<AnyObject> weakRef = new WeakReference<AnyObject>(innerObj1);
The object wrapped inside a WeakReference acts as a diner in a restaurant. When diners finish eating, they are ready to leave the table even if at that time the restaurant has many empty tables. SoftReference is a bit different from WeakReference, diners can sit back and only leave if the restaurant has no more free tables or the number of available free tables is less than a safe value.
4. WeakReference(T, ReferenceQueue<? super T>)
No ADS
Create a WeakReference object that wraps innerObject object. If innerObject is removed from memory by GC, this WeakReference object will be added to the queue.
WeakReference(T innerObject, ReferenceQueue<? super T> queue)
Example:
WeakReference_c2_ex1.java
package org.o7planning.weakreference.ex;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import org.o7planning.beans.AnyObject;
public class WeakReference_c2_ex1 {
public static void main(String[] args) throws InterruptedException {
AnyObject myAnyObject1 = new AnyObject("Obj1");
AnyObject myAnyObject2 = new AnyObject("Obj2");
ReferenceQueue<AnyObject> queue = new ReferenceQueue<AnyObject>();
//
WeakReference<AnyObject> weakRef1 = new WeakReference<AnyObject>(myAnyObject1, queue);
WeakReference<AnyObject> weakRef2 = new WeakReference<AnyObject>(myAnyObject2, queue);
System.out.println("weakRef1: " + weakRef1);
System.out.println("weakRef2: " + weakRef2);
System.out.println("weakRef1.get(): " + weakRef1.get());
System.out.println("weakRef2.get(): " + weakRef2.get());
// Set myAnyObject1 reference to null (Points to null).
myAnyObject1 = null;
System.out.println("\nCall System.gc().\n");
System.gc();
Thread.sleep(3000);
// myAnyObject2 is still used.
System.out.println("myAnyObject2: " + myAnyObject2);
System.out.println("weakRef1.get(): " + weakRef1.get());
System.out.println("weakRef2.get(): " + weakRef2.get());
Reference<? extends AnyObject> removed = null;
while ((removed = queue.poll()) != null) {
System.out.println("removed: " + removed);
}
}
}
Output:
weakRef1: java.lang.ref.WeakReference@5e91993f
weakRef2: java.lang.ref.WeakReference@156643d4
weakRef1.get(): org.o7planning.beans.AnyObject@123a439b
weakRef2.get(): org.o7planning.beans.AnyObject@7de26db8
Call System.gc().
myAnyObject2: org.o7planning.beans.AnyObject@7de26db8
weakRef1.get(): null
weakRef2.get(): org.o7planning.beans.AnyObject@7de26db8
removed: java.lang.ref.WeakReference@5e91993f
5. Complex example
Next, we need a more complex example. In this example, Employee objects are added to a Company. And a List object containing a list of weak references to each Employee object. As long as Company stores Employee objects, they will not be removed from memory by GC.
WeakReference_ex1.java
package org.o7planning.weakreference.ex;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class WeakReference_ex1 {
public static void main(String[] args) throws InterruptedException {
Employee tom = new Employee("Tom");
Employee jerry = new Employee("Jerry");
Employee donald = new Employee("Donald");
Employee[] employees = new Employee[] { tom, jerry, donald };
Company company = new Company();
ReferenceQueue<Employee> queue = new ReferenceQueue<>();
List<WeakReference<Employee>> empListWeak = new ArrayList<WeakReference<Employee>>();
for (int i = 0; i < employees.length; i++) {
company.addEmployee(employees[i]);
empListWeak.add(new WeakReference<Employee>(employees[i], queue));
}
// Free up the array.
employees = null;
System.out.println("Queue's polling returns null? " + (queue.poll() == null));
for (WeakReference<Employee> wref : empListWeak) {
System.out.println("wref.get().getFullName(): " + wref.get().getFullName());
}
//
System.out.println("\n--- Remove some employees from company: ---\n");
company.removeEmployee(tom);
company.removeEmployee(jerry);
tom = null;
jerry = null;
donald = null; // 'donald' is still used in company.
System.gc();
Thread.sleep(3000);
Reference<? extends Employee> wref = null;
System.out.println("Poll weak emp references garbage collected");
while ((wref = queue.poll()) != null) {
System.out.println("WeakReference of Emp removed from queue: " + wref);
}
System.out.println("done");
}
}
class Employee {
private String fullName;
public Employee(String fullName) {
this.fullName = fullName;
}
public String getFullName() {
return this.fullName;
}
}
class Company {
private Set<Employee> employees = new HashSet<Employee>();
public void addEmployee(Employee employee) {
this.employees.add(employee);
}
public void removeEmployee(Employee employee) {
employees.remove(employee);
}
}
Output:
Queue's polling returns null? true
wref.get().getFullName(): Tom
wref.get().getFullName(): Jerry
wref.get().getFullName(): Donald
--- Remove some employees from company: ---
Poll weak emp references garbage collected
WeakReference of Emp removed from queue: java.lang.ref.WeakReference@1175e2db
WeakReference of Emp removed from queue: java.lang.ref.WeakReference@36aa7bc2
done
No ADS
Java Basic
- Data Types in java
- Java PhantomReference Tutorial with Examples
- JDK Javadoc in CHM format
- Java Stream Tutorial with Examples
- Java Predicate Tutorial with Examples
- Java BiConsumer Tutorial with Examples
- Arrays in Java
- JDBC Driver Libraries for different types of database in Java
- Abstract class and Interface in Java
- Java Commons Email Tutorial with Examples
- Install Eclipse
- Bitwise Operations
- Install Eclipse on Ubuntu
- Configuring Eclipse to use the JDK instead of JRE
- Java Commons Logging Tutorial with Examples
- Java Enums Tutorial with Examples
- Loops in Java
- Java Regular Expressions Tutorial with Examples
- Install Java on Ubuntu
- Quick Learning Java for beginners
- Install Java on Windows
- Comparing and Sorting in Java
- Inheritance and polymorphism in Java
- Java Consumer Tutorial with Examples
- Java String, StringBuffer and StringBuilder Tutorial with Examples
- Java Exception Handling Tutorial with Examples
- Example of Java encoding and decoding using Apache Base64
- if else statement in java
- Switch Statement in Java
- Java Supplier Tutorial with Examples
- Java Programming for team using Eclipse and SVN
- Java JDBC Tutorial with Examples
- Java remote method invocation - Java RMI Tutorial with Examples
- Java Multithreading Programming Tutorial with Examples
- Customize java compiler processing your Annotation (Annotation Processing Tool)
- What is needed to get started with Java?
- Java Aspect Oriented Programming with AspectJ (AOP)
- Understanding Java System.identityHashCode, Object.hashCode and Object.equals
- Java Compression and Decompression Tutorial with Examples
- Java Reflection Tutorial with Examples
- Install OpenJDK on Ubuntu
- Java String.format() and printf() methods
- History of Java and the difference between Oracle JDK and OpenJDK
- Introduction to the Raspberry Pi
- Java Socket Programming Tutorial with Examples
- Java Generics Tutorial with Examples
- Manipulating files and directories in Java
- Java WeakReference Tutorial with Examples
- Java Commons IO Tutorial with Examples
- History of bits and bytes in computer science
- Which Platform Should You Choose for Developing Java Desktop Applications?
- Java SoftReference Tutorial with Examples
- Syntax and new features in Java 8
- Java Annotations Tutorial with Examples
- Java Function Tutorial with Examples
- Access modifiers in Java
- Java BiFunction Tutorial with Examples
- Get the values of the columns automatically increment when Insert a record using JDBC
- Java Functional Interface Tutorial with Examples
- Java BiPredicate Tutorial with Examples
Show More
- Java Servlet/Jsp Tutorials
- Java Collections Framework Tutorials
- Java API for HTML & XML
- Java IO Tutorials
- Java Date Time Tutorials
- Spring Boot Tutorials
- Maven Tutorials
- Gradle Tutorials
- Java Web Services Tutorials
- Java SWT Tutorials
- JavaFX Tutorials
- Java Oracle ADF Tutorials
- Struts2 Framework Tutorials
- Spring Cloud Tutorials