Le Tutoriel de Java WeakReference
1. WeakReference
La classe java.lang.ref.WeakReference est utilisée pour créer un objet qui enveloppe (wrap) un autre objet - innerObject. L'objet qu'il enveloppe peut être supprimé de la mémoire par Garbage Collector (GC) s'il n'est plus utilisé ailleurs que par 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;
}
}
Pour mieux comprendre, observer le code ci-dessous:
AnyObject innerObject = new AnyObject("Obj1");
WeakReference weakRef = new WeakReference(innerObject);
Dans le code ci-dessus, nous avons l'objet innerObject, qui est utilisé comme paramètre pour créer l'objet weakRef, ou en d'autres termes innerObject est utilisé par weakRef.
En règle générale, si un objet est utilisé quelque part, il est utile et ne peut pas être supprimé de la mémoire. Cependant, WeakReference est une classe spéciale, considérée comme plus faible que Garbage Collector (GC). L'objet enveloppé dans une WeakReference peut toujours être supprimé de la mémoire par GC s'il n'est plus utilisé ailleurs plus fort que 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
Dans l'exemple ci-dessus, on convoque la méthode System.gc() pour demander au Garbage Collector de travailler. Cette demande n'a pas d'effet immédiat. En règle générale, GC est une machine sophistiquée et complexe qui fonctionne automatiquement et vous ne pouvez l'interférer que de manière limitée.
Dans l'exemple suivant, on n'appellera pas la méthode System.gc(), mais GC supprimera toujours l'objet enveloppé dans WeakReference après un certain temps s'il n'est plus utilisé ailleurs plus fort que 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)
Toutes les méthodes de WeakReference sont héritées de la classe parentale.
// Methods inherited from parent.
public T get()
public void clear()
public boolean isEnqueued()
public boolean enqueue()
2. Primitive Inner Object
Une valeur primitive n'est pas une référence bien qu'elle puisse être écrite comme une référence. Donc, s'il est enveloppé dans une WeakReference, il ne sera pas supprimé de la mémoire par GC.
Integer innerObj1 = 1000;
Double innerObj2 = 2000.2;
String innerObj3 = "SomeString";
Par exemple:
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
Si un objet est créé par un opérateur "new" et enveloppé dans une WeakReference, il sera supprimé de la mémoire par GC s'il n'est plus utilisé ailleurs plus fort que 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);
L'objet enveloppé dans une WeakReference agit comme un diner dans un restaurant. Lorsque les convives ont fini de manger, ils sont prêts à quitter la table même si à ce moment-là le restaurant a de nombreuses tables vides. SoftReference est un peu différent de WeakReference, les convives peuvent s'asseoir et ne partir que si le restaurant n'a plus de tables libres ou si le nombre de tables libres disponibles est inférieur à une valeur sûre.
4. WeakReference(T, ReferenceQueue<? super T>)
Créer un objet WeakReference qui enveloppe l'objet innerObject. Si innerObject est supprimé de la mémoire par GC, cet objet WeakReference sera ajouté dans queue.
WeakReference(T innerObject, ReferenceQueue<? super T> queue)
Par exemple:
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
Ensuite, on a besoin d'un exemple plus complexe. Dans cet exemple, les objets Employee sont ajoutés à une Company. Et un objet List contenant une liste de références faibles à chaque objet Employee. Tant que la Company stocke les objets Employee, ils ne seront pas supprimés de la mémoire par le 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
Java Basic
- Personnaliser le compilateur Java pour traiter votre annotation (Annotation Processing Tool)
- Programmation Java pour l'équipe utilisant Eclipse et SVN
- Le Tutoriel de Java WeakReference
- Le Tutoriel de Java PhantomReference
- Tutoriel sur la compression et la décompression Java
- Configuration d'Eclipse pour utiliser le JDK au lieu de JRE
- Méthodes Java String.format() et printf()
- Syntaxe et nouvelles fonctionnalités de Java 8
- Expression régulière en Java
- Tutoriel de programmation Java multithreading
- Bibliothèques de pilotes JDBC pour différents types de bases de données en Java
- Tutoriel Java JDBC
- Obtenir des valeurs de colonne automatiquement incrémentées lors de l'insertion d'un enregistrement à l'aide de JDBC
- Le Tutoriel de Java Stream
- Le Tutoriel de Java Functional Interface
- Introduction à Raspberry Pi
- Le Tutoriel de Java Predicate
- Classe abstraite et interface en Java
- Modificateurs d'accès en Java
- Le Tutoriel de Java Enum
- Le Tutoriel de Java Annotation
- Comparer et trier en Java
- Le Tutoriel de Java String, StringBuffer et StringBuilder
- Tutoriel de gestion des exceptions Java
- Le Tutoriel de Java Generics
- Manipulation de fichiers et de répertoires en Java
- Le Tutoriel de Java BiPredicate
- Le Tutoriel de Java Consumer
- Le Tutoriel de Java BiConsumer
- Qu'est-ce qui est nécessaire pour commencer avec Java?
- L'histoire de Java et la différence entre Oracle JDK et OpenJDK
- Installer Java sur Windows
- Installer Java sur Ubuntu
- Installer OpenJDK sur Ubuntu
- Installer Eclipse
- Installer Eclipse sur Ubuntu
- Le Tutoriel Java pour débutant
- Histoire des bits et des bytes en informatique
- Types de données dans Java
- Opérations sur les bits
- Le Tutoriel de instruction Java If else
- Le Tutoriel de instruction Java Switch
- Les Boucles en Java
- Les Tableaux (Array) en Java
- JDK Javadoc au format CHM
- Héritage et polymorphisme en Java
- Le Tutoriel de Java Function
- Le Tutoriel de Java BiFunction
- Exemple de Java encoding et decoding utilisant Apache Base64
- Le Tutoriel de Java Reflection
- Invocation de méthode à distance en Java
- Le Tutoriel de Java Socket
- Quelle plate-forme devez-vous choisir pour développer des applications de bureau Java?
- Le Tutoriel de Java Commons IO
- Le Tutoriel de Java Commons Email
- Le Tutoriel de Java Commons Logging
- Comprendre Java System.identityHashCode, Object.hashCode et Object.equals
- Le Tutoriel de Java SoftReference
- Le Tutoriel de Java Supplier
- Programmation orientée aspect Java avec AspectJ (AOP)
Show More
- Tutoriels de programmation Java Servlet/JSP
- Tutoriels de Java Collections Framework
- Tutoriels Java API pour HTML & XML
- Tutoriels Java IO
- Tutoriels Java Date Time
- Tutoriels Spring Boot
- Tutoriels Maven
- Tutoriels Gradle
- Tutoriels Java Web Service
- Tutoriels de programmation Java SWT
- Tutoriels de JavaFX
- Tutoriels Java Oracle ADF
- Tutoriels Struts2
- Tutoriels Spring Cloud