Angelika Langer - Training & Consulting
HOME | COURSES | TALKS | ARTICLES | GENERICS | LAMBDAS | IOSTREAMS | ABOUT | CONTACT | Twitter | Lanyrd | Linkedin
 
HOME 

  OVERVIEW

  BY TOPIC
    JAVA
    C++

  BY COLUMN
    EFFECTIVE JAVA
    EFFECTIVE STDLIB

  BY MAGAZINE
    JAVA MAGAZIN
    JAVA SPEKTRUM
    JAVA WORLD
    JAVA SOLUTIONS
    JAVA PRO
    C++ REPORT
    CUJ
    OTHER
 

GENERICS 
LAMBDAS 
IOSTREAMS 
ABOUT 
CONTACT 
Effective Java - Weak References

Effective Java - Weak References  
Memory Leaks
Weak References
 

Java Magazin, Juni 2013
Klaus Kreft & Angelika Langer

Dies ist die Überarbeitung eines Manuskripts für einen Artikel, der im Rahmen einer Kolumne mit dem Titel "Effective Java" im Java Magazin erschienen ist.  Die übrigen Artikel dieser Serie sind ebenfalls verfügbar ( click here ).

 

I n den vorangegangenen Beiträgen zum Thema Memory Leaks in Java haben wir uns angesehen, wie Memory Leaks entstehen (/MEM1/ bis /MEM3/)) und mit welchen Techniken und Tools man nach ihnen suchen kann (/ MEMLKS-4 / bis / MEMLKS-5 /).  Dieses Mal wollen wir uns  WeakReference s genauer ansehen.  Mit ihrer Hilfe ist es möglich, Situationen zu vermeiden, in denen Memory Leaks entstehen können.

Memory Leaks in Java

Gehen wir noch einmal zurück zu dem Beispiel eines Memory Leaks, das wir ausführlich im ersten Artikel zum Thema Memory Leaks diskutiert haben (/ MEMLKS-1 /).   In dem Beispiel haben wir einen rudimentären Server auf Basis der mit Java 7 eingeführten  AsynchronousSocketChannel s implementiert.  Das Memory Leak entstand dadurch, dass wir im Server für jeden neuen Client Verwaltungsinformation in einer Map gespeichert haben und diese client-spezifischen Map-Einträge nicht nach der Beendigung der Kommunikation mit den jeweiligen Clients wieder gelöscht haben.  Es ist offensichtlich, dass sich die Map mit jedem neuen Client vergrößert.  Erzeugt man also in einem Testprogramm viele Clients hintereinander, so stürzt der Server irgendwann mit einem  OutOfMemoryError ab.  Der Sourcecode zu dem Beispiel sowie verschiedene alternative Korrekturen finden sich hier (/ SRC /).

 
 

Wie wir in dem darauf folgenden Artikel (/ MEMLKS-2 /) diskutiert haben, ist diese Situation relativ typisch für ein Memory Leak, das zu einem  OutOfMemoryError führt.  Es gibt in Java häufig Verwaltungen, in die man Objekte eintragen und, wenn sie nicht mehr benötigt werden, auch wieder löschen muss.  Ein weiteres Beispiel, das wir uns dazu angesehen haben, ist die Verwaltung der Callbacks, die man als AWT Event Listener einhängt.
 
 

In unserer Artikelserie sind wir bisher so verblieben, dass es Aufgabe des Benutzers ist, solche Verwaltungen korrekt zu verwenden. Das heißt, er muss darauf achten, dass er jedes Objekt, das er in eine solche Verwaltung eingetragen hat, auch zum angemessenen Zeitpunkt wieder löscht. Wenn er sich nicht daran hält, hat er als Konsequenz das entstandene Memory Leak und den eventuell folgenden Programmabsturz auf Grund eines  OutOfMemoryError zu verantworten.

Ungewollte Referenzen und  WeakReference s

In diesem Artikel wollen wir nun schauen, ob derjenige, der die Verwaltung implementiert und bereitstellt, nicht auch etwas tun kann, damit es erst gar nicht zu Memory Leaks kommen kann.  Toll wäre es doch, wenn der Benutzer sich gar nicht um das Löschen kümmern müßte, weil dies automatisch erledigt wird.

 
 

Um zu verstehen, wie so etwas gehen könnte, rufen wir uns noch mal in Erinnerung, wie es genau zu einem Memory Leak kommt.  Der Garbage Collector ermittelt ausgehend von sogenannten Root References , welche Objekte in einem Java Programm referenziert und damit erreichbar sind.  Alle nicht erreichbaren Objekte räumt der Garbage Collector bei der Garbage Collection weg und gibt ihren Speicher frei.  Wenn wir nun auf ein Objekt verweisen, von dem wir sicher sagen können, dass wir es im weiteren Kontext unseres Programms gar nicht mehr benutzen werden, haben wir ein Memory Leak,  denn das nicht mehr benötigte Objekt wird vom Garbage Collector nicht weggeräumt, weil es noch referenziert wird.  Diese Referenz wird in der englischsprachigen Fachliteratur unwanted reference (also: ungewollte Referenz) genannt.
 
 

Übertragen wir diese Beschreibung auf das Memory-Leak-Beispiel aus dem ersten Artikel: Die client-spezifischen Verwaltungsdaten werden auch nach der Beendigung der Kommunikation mit dem Client weiter über die Map referenziert, so dass der Garbage Collector sie nicht freigeben kann.  Die Map mit ihrer internen Datenstruktur bildet also unsere ungewollte Referenz auf die client-spezifischen Daten. 
 
 

Wie wäre es denn nun, wenn man dem Garbage Collector explizit sagen könnte, dass die ungewollten Referenzen genau dies sind: ungewollt.  Man möchte ausdrücken, dass diese Referenzen zwar für die Navigation im Objektgraphen der Applikation zur Verfügung stehen, damit man die Objekte erreichen kann.  Aber für den Garbage Collector soll es nicht bedeuten, dass die Objekte, auf die sie verweisen, am Leben gehalten werden sollen.  Genau zu diesem Zweck gibt es seit dem JDK 1.2 das Package  java.lang.ref im JDK, mit dem neben einigen weiteren Referenztypen (siehe Textbox: „Referenztypen im JDK“) die sogenannten  WeakReference s eingeführt wurden. 
 
 

Die Idee ist, dass man ungewollte Referenzen innerhalb einer Datenverwaltung als  WeakReference s implementiert. Damit braucht sich der Benutzer der Datenverwaltung nicht mehr um das Löschen der Objekte, die er in die Datenverwaltung eingetragen hat, kümmern.  Das Löschen wird statt dessen automatisch vom Garbage Collector erledigt.  Wie das Ganze im Detail geht, wollen wir weiter unten am Beispiel des Servers aus dem ersten Artikel (/ MEMLKS-1 /) diskutieren.  Als erstes sehen wir uns aber die  WeakReference selbst etwas genauer an.

Die  WeakReference im Detail

Fangen wir zuerst mit der Namensgebung an.  Da man auf ein Objekt über eine normale Referenz und über eine  WeakReference verweisen kann, reicht ein Verb wie „referenzieren“ nicht mehr aus, um die spezifische Art der Referenz zu beschreiben.  In der englischen Fachliteratur haben sich deshalb die Ausdrücke strongly referenced für das Referenzieren über eine normale Referenz und weakly referenced für das Referenzieren über eine  WeakReference gebildet.  In Anlehnung daran werden wir die Ausdrücke strong-referenziert bzw. weak-referenziert verwenden. Entsprechend ergibt sich: ein Objekt, das strong-erreichbar (also über normale Referenzen erreichbar) ist, wird nicht vom  Garbage Collector freigegeben wird; ein Objekt das weak-erreichbar ist, wird hingegen trotz der Erreichbarkeit vom Garbage Collector freigegeben. 

 
 

Dabei gilt ein Objekt als weak-erreichbar, wenn alle Referenzketten von den Root-Referenzen auf das fragliche Objekt mindestens eine Weak-Referenz enthalten. In der Verweiskette können durchaus auch normale Referenzen vorkommen, aber die Verweiskette muss mindestens eine Weak-Referenz enthalten, damit das referenzierte Objekt als weak-erreichbar gilt. Abbildung 1 zeigt eine solche Situation, in der ein Sting nur noch weak-erreichbar ist, obwohl es eine direkte Strong-Referenz auf den String gibt.

Abbildung 1: weak-erreichbarer String
 
 
 
 

Schauen wir uns nun an, wie man eine  WeakReference benutzt.  Beginnen wir mit einer Klasse  MyClass , die ein Feld vom Typ  String hat.  Das bedeutet in der Terminologie von oben, dass eine Instanz von  MyClass das enthaltene String-Objekt strong-referenziert.  Die dazugehörende recht rudimentäre Implementierung unserer Beispielklasse sieht folgendermaßen aus:
 
 

public class MyClass {

   private String myString;

   public MyClass(String s) { 

       myString = s; 

    }

   public boolean doSomething(String o) {

       return myString.equalsIgnoreCase(o);

   }

}
 
 

Wie sieht die Implementierung von  MyClass nun aus, wenn wir den String nicht mehr strong- sondern weak-referenzieren wollen?  Die  WeakReference ist eine generische Klasse, die als Weak-Referenz-Wrapper um das Originalobjekt fungiert, so dass wir dann folgende Implementierung bekommen:
 
 

public class MyClass {

   private WeakReference<String> myWeakString;

   public MyClass(String s) { 

      myWeakString = new WeakReference<String>(s); 

   }

   public boolean doSomething(String o) {

      String s = myWeakString.get();

      if (s == null)

         return false;

      else

         return s.equalsIgnoreCase(o);

    }

}
 
 

Um auf das eigentliche Objekt, das weak-referenziert wird, zugreifen zu können, muss temporär eine Strong-Referenz genutzt werden.  In unserem Beispiel ist dies die Stackvariable  s vom Typ  String in der Methode  doSomething() .  Die  WeakReference liefert die Strong-Referenz beim Aufruf von  get() zurück, wenn das referenzierte Objekt noch existiert.   get() liefert  null zurück, wenn das Objekt irgendwann vorher nur noch weak-erreichbar war und deshalb bereits vom Garbage Collector weggeräumt worden ist.  Beim Zugriff auf das referenzierte Objekt muss man also immer darauf vorbereitet sein, dass das Objekt gar nicht mehr existiert, und entsprechend im Programm mit dieser Situation umgehen können.
 
 

Es gibt noch ein weiteres interessantes Features von  WeakReference s.  Es ist möglich bei der Konstruktion einer  WeakReference anzugeben, dass man informiert werden möchte, wenn das Objekt, auf das diese Referenz verweist, vom Garbage Collector weggeräumt worden ist.  Zu diesem Zweck muss man als zusätzliches Konstruktor-Argument ein Queue vom Typ  ReferenceQueue aus dem Package  java.lang.ref mitgeben. Der Garbage Collector stellt eine so konstruierte  WeakReference - Instanz in die Queue, sobald er festgestellt hat, dass das referenzierte Objekt nur noch weak-erreichbar ist. In der  ReferenceQueue findet man also all die  WeakReference s, deren Objekte der Garbage Collector demnächst wegräumen wird oder bereits weggeräumt hat. Dieser Mechanismus erlaubt es dem Benutzer der  WeakReference nun, auf diese Situation zu reagieren.  Wie das konkret aussehen kann, werden wir weiter unten sehen.

Die  Weak HashMap als Lösung für das Memory-Leak-Beispiel

Kommen wir wieder zurück zu unserm Memory-Leak-Beispiel aus dem ersten Artikel der Serie (/ MEMLKS-1 /).  Wie oben bereits erwähnt, entstand das Memory Leak dadurch, dass wir für jeden neuen Client Verwaltungsinformation in einer Map gespeichert haben und diese clientspezifischen Map-Einträge nicht nach der Beendigung der Kommunikation mit den jeweiligen Clients wieder gelöscht haben.  Der Key des Map-Eintrags war die  ClientSession und das Value der  AsynchronousSocketChannel des jeweiligen Clients. Die Map, die verwendet wurde, ist als Feld der  Server -Klasse folgendermaßen definiert:

 
 

   private final Map<ClientSession, AsynchronousSocketChannel> sessionToChannel = 

                      new ConcurrentHashMap<ClientSession, AsynchronousSocketChannel>();
 
 

Die Map ist vom Typ  ConcurrentHashMap , weil die  completed() -Methoden der  read() -Callbacks konkurrierend auf die Map zugreifen.  Wie oben bereits gesagt, kann man den vollständigen Code unter / SRC / herunterladen.
 
 

Die Idee ist nun, die ungewollte Referenzen, die unsere Map auf die  ClientSession und den  AsynchronousSocketChannel hält, geschickt durch  WeakReference s zu ersetzen und so das Memory Leak zu vermeiden.  Die Sourcecode-Änderung für diese Korrektur ist minimal.  Die Erklärung, warum sie funktioniert, ist erheblich länger.  Also schauen wir uns zuerst die Änderung an, dann kommen wir zu den ausführlichen Erläuterungen.
 
 

Die Änderung besteht darin,  dass wir die Map nun folgendermaßen definieren:
 
 

private final Map<ClientSession, AsynchronousSocketChannel> sessionToChannel = 

            Collections.synchronizedMap(new WeakHashMap<ClientSession, AsynchronousSocketChannel>()) ;

Die primäre Idee ist, eine  WeakHashMap zu verwenden.  Da diese aber nicht thread-sicher bei konkurrierendem Zugriff ist, müssen wir zusätzlich einen  synchronizedMap -Wrapper verwenden.  Zugegeben, bei hoher Last wird die  synchronizedMap nicht so gut skalieren wie eine  ConcurrentHashMap .  Aber mit diesem Nachteil wollen wir leben, denn immerhin haben wir so mit minimalem Aufwand das Memory Leak behoben. 
 
 

Warum das so ist und wie die  WeakHashMap im Detail funktioniert, wollen wir uns nun ansehen.  Wie die  WeakReference kam auch die  WeakHashMap mit der Version 1.2 zum JDK dazu.  Die  WeakHashMap implementiert eine Hash-Map, bei der der Key nur weak-referenziert wird.  Das heißt, wenn das Key-Objekt eines Eintrags nicht von anderer Stelle im Programm strong-referenziert wird,  räumt der Garbage Collector das Key-Objekt weg.  Die  WeakHashMap lässt sich darüber vom Garbage Collector informieren. Dies geht über den Mechanismus mit der  ReferenceQueue , den wir oben bereits beschrieben haben.  Als Reaktion auf diese Notifikation löscht die  WeakHashMap den gesamten noch verbliebenen Eintrag bestehend aus der (bereits entleerten)  WeakReference als Key und dem dazugehörigen Value.
 
 

In unserem Beispiel löst die  WeakHashMap das Memory-Leak-Problem. Entscheidend dafür ist, dass der Key (d.h. die  ClientSession ) genau so lange von außerhalb der Map strong-referenziert wird, wie die Verbindung mit dem Client besteht.  Dies ist bei uns gegeben, wie ein Blick auf die  complete d () -Methode des  read() - Callbacks bestätigt:
 
 

public void completed(Integer len,  ClientSession clSession ) {

    AsynchronousSocketChannel channel = sessionToChannel.get(clSession);

    if (clSession.handleInput(buf, len)) {

       buf.clear();

      channel.read(buf,  clSession , this);

   }

   else {

      try { 

         channel.close();

      } catch (IOException e) { /* ignore */ }

   }

}
 
 

Wie man sehen kann, schleusen wir die  ClientSession immer wieder als zweiten Parameter des  read() zum nächsten Callback-Aufruf.  Das heißt, die notwendige Strong-Referenz auf das  ClientSession -Objekt kommt aus dem  AsynchronousSocketChannel -Framework im JDK, wo das Objekt für den nächsten Callback-Aufruf über eine Strong-Referenz zwischengespeichert wird.  Offensichtlich ist auch, dass diese Strong-Referenz nicht mehr existiert, wenn die Kommunikation mit dem Client beendet ist.  Dann landen wir nämlich im  else -Zweig der  completed() -Methode und es wird kein erneuter  read() -Aufruf (mit der  ClientSession als Parameter) gemacht.
 
 

Auf den ersten Blick mag es so aussehen, dass es allein ein glücklicher Zufall ist, dass die  WeakHashMap mit so geringem Aufwand unser Memory-Leak-Problem löst.  Dem ist aber nicht so.  Die Situation ist sogar eher typisch.  Denn im allgemeinen hat man eine Strong-Referenz auf das Key-Objekt, mit dem man auf die Map zugreift, bis zu dem Zeitpunkt, wo dann die Map zur ungewollten Referenz auf das Key-Objekt und das Value-Objekt wird.  Genau da hilft einem dann das spezifische Verhalten der  WeakHashMap , denn Key- und Value-Objekt werden nun von der  WeakHashMap in Zusammenarbeit mit dem GarbageCollector freigegeben.

Die  Weak HashMap im Detail

Werfen wir am Ende noch einen Blick auf einige Implementierungsdetails der  WeakHashMap .  Dies hilft auch zu verstehen, wie man  WeakReference s in eigenen Implementierungen sinnvoll einsetzt.

 
 

Typisch ist, dass man meist nicht die  WeakReference direkt nutzt, sondern eine Klasse davon ableitet, die zusätzliche Attribute und Funktionalität enthält.  Bei der  WeakHashMap ist diese von  WeakReference abgeleitete Klasse die private Inner Class  E ntry , die zusätzlich das Interface  Map.Entry implementiert:
 
 

private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> { ... }
 
 

Ein  Entry besteht aus dem eigentlichen Key-Value-Paar und zusätzlich eine Reihe von weiteren Attributen.  Dabei besteht das Key-Value-Paar aus einer Weak-Referenz auf den Key und einer Strong-Referenz auf das Value.
 
 

Die Bestandteile eines  Entry kann man gut an der Implementierung des Konstruktors von  Entry sehen:
 
 

Entry(Object key, V value, ReferenceQueue<Object> queue, int hash, Entry<K,V> next) {

   super(key, queue);

   this.value = value;

   this.hash  = hash;

   this.next  = next;

}
 
 

Der Key wird als erstes Argument an den Konstruktor der Superklasse   WeakReference übergeben.  Damit ist  der Key nicht über eine normale Strong-Referenz im  Entry abgelegt, sondern in eine Weak-Referenz verpackt. Das Value hingegen ist über eine normale Referenz (als Attribut  value ) im  Entry abgelegt.
 
 

An den Konstruktor der Superklasse   WeakReference wird neben dem Key als zweites Argument die Queue übergeben, in der die  WeakReference - Instanzen (oder genauer: die  Entry - Instanzen) landen, deren weak-referenzierte Objekte vom Garbage Collector weggeräumt werden.  Diese Queue wird später von der privaten Methode  expungeStaleEntries() verwendet, um Key-Value-Paare mit nur noch weak-erreichbarem Key aus der Map zu entfernen (siehe unten).
 
 

Ganz wichtig ist der Hashcode, der im  Entry abgelegt ist.  Er wird von der privaten Methode  expungeStaleEntries ()  benötigt, um die Key-Value-Paare mit weak-erreichbarem Key in der Map zu finden und zu entfernen.  Der Key ist ja nur noch weak-erreichbar (oder schon ganz weggeräumt) und kann deshalb nicht mehr verwendet werden. Es wird dabei ausgenutzt, dass die Positionen der Entries in der Map vom Hashcode der Entries abhängen.  Für die Berechnung des Hashcodes eines  Entry s wird der Hashcode des Keys benötigt.  Wie bereits erwähnt, ist der Key aber nur noch weak-erreichbar und möglicherweise sogar bereits vom Garbage Collector weggeräumt worden. Genau deshalb wird der Hashcode des Keys im  Entry als eigenes Feld gespeichert.  Auf diese Weise ist der Hashcode des Keys noch verfügbar, wenn der Key selbst bereits verschwunden ist.  So kann das Entry dann in der Map gelöscht werden.
 
 

Die private Methode  expungeStaleEntries()  wird in den  public Methoden der  WeakHashMap aufgerufen.  Wir haben die  WeakHashMap  in einen  synchronizedMap -Wrapper verpackt; der  synchronizedMap -Wrapper sorgt dafür, dass alle  public Methoden synchronisiert sind. Damit ist auch das interne Löschen der  Entry s aus der  WeakHashMap gegen konkurrierende Zugriffe von Außen auf die  WeakHashMap geschützt und unsere Lösung ist thread-sicher.

Zusammenfassung und Ausblick

In diesem Artikel haben wir uns angesehen, wie  WeakReference s helfen können, Memory Leaks zu vermeiden.  Die zentrale Idee dabei ist, die ungewollten Referenzen in Verwaltungen, die zu Memory Leaks führen, als  WeakReference s zu implementieren.  Handelt es sich bei der Verwaltung um eine Map, so kann man in vielen Fällen gleich die  WeakHashMap benutzen.  Die eigentliche Änderung im Code ist dann mit sehr geringem Aufwand verbunden, wie wir in unserem Beispiel gesehen haben.

 
 

Mit diesem Artikel schließen wir unsere Reihe über Memory Leaks in Java.  Das nächste Thema, dem wir uns widmen werden, ist Java 8 und die dazugehörigen Neuerungen.  Der erste Artikel dazu wird in der Ausgabe 9.2013 des Java Magazin erscheinen.
 
 
 
Referenztypen im JDK

 
Neben der  WeakReference sind mit Java 1.2 auch die  SoftReference und die  PhantomReference zum JDK dazu gekommen.

 
 

Die   SoftReferences haben dasselbe API wie  WeakReferences .  Charakteristisch ist für sie, dass in ihrer JavaDoc relativ explizite Aussage gemacht werden, wann und wie sie vom Garbage Collector weggeräumt werden:
 
 

All soft references to softly-reachable objects are guaranteed to have been cleared before the virtual machine throws an  OutOfMemoryError . Otherwise no constraints are placed upon the time at which a soft reference will be cleared or the order in which a set of such references to different objects will be cleared. Virtual machine implementations are, however, encouraged to bias against clearing recently-created or recently-used soft references.
 
 

Die Idee ist, dass man  SoftReference s dazu nutzt, um eigene Cashes zu implementieren. Die gecachten Objekte werden im Cache über  SoftReferences referenziert.  So wird die Cachegröße über den Garbage Collector kontrolliert. Bevor der Cache zu groß wird und die JVM mit  OutOfMemoryError abstürzt, werden die soft-referenzierten Objekte im Cache vom Garbage Collector weggeräumt.  Das ganze klingt erst einmal wie ein ziemlich schlüssiges Konzept.  In der Praxis hat sich der Ansatz aber als nicht so problemlos erwiesen.  Das liegt zu einen daran, dass die Behandlung der  SoftReference s und somit auch das Cache-Verhalten vom konkret genutzten Garbage Collection Algorithmus abhängt.  Das ist eine Abhängigkeit, der man sich häufig nicht bewusst ist und die man meist auch nicht haben möchte.  Zum anderen bedeutet das Wegräumen der  SoftReference s zusätzliche Arbeit für den Garbage Collector.  Wenn nun beim Programmablauf möglichst kurze Garbage Collection Pausen erreicht werden sollen, ist die Benutzung von  SoftReference s für den Cache kontraproduktiv.
 
 

Unterm Strich bleibt festzustellen, dass es meist keine gute Idee ist, die Cachegröße allein mit Hilfe von  SoftReference s über den Garbage Collector zu kontrollieren.  Es macht aber durchaus Sinne, eine eigene Cachegrößen-Kontrolle zu implementieren und die  SoftReference s als zusätzliches Sicherheitsnetz zu nutzen, damit der Cache die JVM nicht mit  OutOfMemoryError abstürzen läßt.
 
 

Die PhantomReference s sind völlig anders als die Weak- und Soft-Referenzen. Wie wir in diesem Beitrag erläutert haben, werden  weak- oder soft-erreichbare Objekte vom Garbage Collector nach unterschiedlichen Strategien weggeräumt und es bleiben leere Referenzen übrig. Die Phantom-Referenzen bewirken das Gegenteil: sie verhindern die Speicherfreigabe der referenzierten Objekte.  Eine  PhantomReference auf ein Objekt besteht sogar dann noch, wenn der Garbage Collector den Finalizer für das referenzierte Objekt bereits ausgeführt hat. Es bleibt eine Phantom-Referenz auf ein finalisiertes und damit unbrauchbares Objekt zurück, das bereits alle seine Ressourcen abgeräumt hat.  Deshalb werden die  PhantomReference s auch als Post-Mortem-Referenzen bezeichnet: eigentlich ist das referenzierte Objekt schon tot und die Referenz verweist nur noch auf einen nicht mehr genutzten Speicherbereich ohne sinnvollen Inhalt.
 
 

PhantomReference s waren für die Implementierung eigener Memory-Pools gedacht. Mit Hilfe der PhantomReference s könnte man die Pool-Elemente am Memory Management des Garbage Collectors vorbei recyceln und wiederbenutzen. Da aber die heutigen Garbage Collectoren ihre Aufgabe so gut erledigen, dass es in der Praxis wenig Sinn macht, einen eigenen Memory-Pool in der Anwendung zu implementieren, sind  PhantomReference s in der Praxis bedeutungslos und hier nur der Vollständigkeit halber erwähnt. 

 

Literaturverweise

Die gesamte Serie über Memory Leaks:

/MEMLKS-1/ Memory Leaks - Ein Beispiel
Klaus Kreft & Angelika Langer, Java Magazin, August 2012
URL: http://www.angelikalanger.com/Articles/EffectiveJava/64.Mem.Leaks/64.Mem.Leaks.html
/MEMLKS-2/ Akkumulation von Memory Leaks
Klaus Kreft & Angelika Langer, Java Magazin, Oktober 2012
URL: http://www.angelikalanger.com/Articles/EffectiveJava/65.Mem.Akkumulation/65.Mem.Akkumulation.html
/MEMLKS-3/ Memory Leaks - Referenzen "ausnullen"
Klaus Kreft & Angelika Langer, Java Magazin, Dezember 2012
URL: http://www.angelikalanger.com/Articles/EffectiveJava/66.Mem.NullOut/66.Mem.NullOut.html
/MEMLKS-4/ Tools für die dynamisch Memory Leak Analyse
Klaus Kreft & Angelika Langer, Java Magazin, Februar 2013
URL: http://www.angelikalanger.com/Articles/EffectiveJava/67.MemLeak.ToolCyclic/67.MemLeak.ToolCyclic.html
/MEMLKS-5/ Heap Dump Analyse
Klaus Kreft & Angelika Langer, Java Magazin, April 2013
URL: http://www.angelikalanger.com/Articles/EffectiveJava/68.MemLeak.ToolDump/68.MemLeak.ToolDump.html
/MEMLKS-6/ Weak References
Klaus Kreft & Angelika Langer, Java Magazin, Juni 2013
URL: http://www.angelikalanger.com/Articles/EffectiveJava/69.MemLeak.WeakRefs/69.MemLeak.WeakRefs.html

 
 
 
 

If you are interested to hear more about this and related topics you might want to check out the following seminar:
Seminar
 
Effective Java - Advanced Java Programming Idioms 
4 day seminar ( open enrollment and on-site)
High-Performance Java - Profiling and Tuning Java Applications
4 day seminar ( open enrollment and on-site)
 

 
 
  © Copyright 1995-2016 by Angelika Langer.  All Rights Reserved.    URL: < http://www.AngelikaLanger.com/Articles/EffectiveJava/69.MemLeak.WeakRefs/69.MemLeak.WeakRefs.html  last update: 29 Nov 2016