2012-03-29 7 views
17

Ich habe zwei separate Caches, die in einer JVM ausgeführt werden (eine, die von einer Bibliothek eines Drittanbieters gesteuert wird), die jeweils weiche Referenzen verwenden. Ich würde es vorziehen, wenn die JVM meinen kontrollierten Cache vor dem von der Bibliothek kontrollierten Cache löscht. Die Softreference javadoc Zustände:Wie werden SoftReferences von JVMs in der Praxis gesammelt?

Alle weichen Verweise auf sanft erreichbare Objekte sind garantiert haben bevor die virtuelle Maschine eine OutOfMemoryError wirft gelöscht. Andernfalls werden keine Bedingungen für den Zeitpunkt festgelegt, zu dem eine weiche Referenz gelöscht wird, oder die Reihenfolge, in der ein Satz solcher Referenzen auf verschiedene Objekte gelöscht wird. Virtuelle Maschinen Implementierungen werden jedoch dazu ermutigt, vor dem Löschen vor kurzem erstellte oder kürzlich verwendete Soft-Referenzen zu systematisieren.

Direkte Instanzen dieser Klasse können zum Implementieren einfacher Caches verwendet werden. Diese Klasse oder abgeleitete Unterklassen können auch in größeren Daten Strukturen verwendet werden, um anspruchsvollere Caches zu implementieren. Solange der Referent einer Soft-Referenz stark erreichbar ist, dh tatsächlich verwendet wird, wird die Soft-Referenz nicht gelöscht. So kann ein ausgeklügelter Cache z. B. verhindern, dass seine zuletzt verwendeten Einträge verworfen werden, indem starke Referenzen zu diesen Einträgen beibehalten werden, wobei die verbleibenden Einträge unter der Diskretion des Garbage Collectors verworfen werden.

Wie gehen gängige JVM-Implementierungen, insbesondere HotSpot, mit SoftReferences in der Praxis um? Sind sie "voreingenommen gegen das Löschen kürzlich erstellter oder kürzlich verwendeter weicher Referenzen", wie es von der Spezifikation gefordert wird?

+0

relevant? [Wie Hotspot beschließt, SoftReferences zu löschen] (http://jeremymanson.blogspot.com/2009/07/how-hotspot-decide-to-clear_07.html) –

+1

@MiserableVariable Ja, ziemlich relevant, obwohl Ihr Link einen Brief fehlt : http://jeremymanson.blogspot.com/2009/07/how-hotspot-decides-to-clear_07.html –

+0

Es fehlte es nicht früher, aber ich musste klug handeln und einen Link daraus machen .. Da Ich weigere mich, die Dokumentation zu lesen und versuche es durch Versuch und Irrtum, manchmal wird echter Inhalt gelöscht. Wen kümmert es, solange es schön aussieht, oder? –

Antwort

6

Sieht so aus, als könnte es abstimmbar sein, ist es aber nicht. Der gleichzeitige Mark-Sweep-Kollektor hängt an der Implementierung des Standardheaps von must_clear_all_soft_refs(), die anscheinend nur true ist, wenn eine _last_ditch_collection ausgeführt wird.

bool GenCollectedHeap::must_clear_all_soft_refs() { 
    return _gc_cause == GCCause::_last_ditch_collection; 
} 

Während normale Handhabung ausgefallener Zuteilung hat drei aufeinander folgende Aufrufe an den do_collect Methode Heap, in den CollectorPolicy.cpp

HeapWord* GenCollectorPolicy::satisfy_failed_allocation(size_t size, 
                bool is_tlab) { 

Welche zu sammeln versucht, neu zu verteilen versucht, versucht, den Haufen zu erweitern, wenn das fehlschlägt und versucht dann als letzten Versuch, Clearing-Soft-Referenzen zu sammeln.

Der Kommentar in der letzten Kollektion ganz (und die einzige, die weich Refs Trigger Clearing) sagt

// If we reach this point, we're really out of memory. Try every trick 
    // we can to reclaim memory. Force collection of soft references. Force 
    // a complete compaction of the heap. Any additional methods for finding 
    // free memory should be here, especially if they are expensive. If this 
    // attempt fails, an OOM exception will be thrown. 
    { 
    IntFlagSetting flag_change(MarkSweepAlwaysCompactCount, 1); // Make sure the heap is fully compacted 

    gch->do_collection(true    /* full */, 
         true    /* clear_all_soft_refs */, 
         size    /* size */, 
         is_tlab   /* is_tlab */, 
         number_of_generations() - 1 /* max_level */); 
    } 

--- Edited in Reaktion auf die Hand, ich beschrieb schwache Verweise, nicht weich diejenigen ---

In der Praxis würde ich mir vorstellen, dass SoftReferences nur "nicht" gefolgt werden, wenn die JVM für Garbage Collection aufgerufen wird als Antwort auf sie versuchen, eine zu vermeiden.

Für SoftReference s kompatibel zu allen vier Java 1.4 Garbage Collectors und mit dem neuen G1 Collector muss die Entscheidung nur bei der Erreichbarkeitsbestimmung liegen. Wenn das Ernten und Verdichten stattfindet, ist es viel zu spät, um zu entscheiden, ob ein Objekt erreichbar ist.Dies legt nahe (aber ist nicht erforderlich), dass ein Sammlungs- "Kontext" existiert, der die Erreichbarkeit basierend auf der Verfügbarkeit von freiem Speicher in dem Heap bestimmt. Ein solcher Kontext müsste anzeigen, dass man nicht vor dem Versuch, ihnen zu folgen, SoftReferences folgt.

Da OutOfMemoryError Vermeidung Garbage Collection speziell in einer vollständigen Sammlung geplant ist, Stop-the-World Art und Weise, wäre es nicht ein schwer vorstellbar Szenario, wo der Heap-Manager ein "Do not follow SoftReference" -Flag vor der Sammlung erfolgt.

--- Ok, also habe ich beschlossen, dass ein „muss so funktionieren“ beantworten gerade genug ---

aus dem Quellcode src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp (Highlights sind mir) nicht gut war

Der Betrieb tatsächlich "do" Garbage collection:

170 void VM_GenCollectFullConcurrent::doit() { 

Wir sollten besser ein VM-Thread sein, andernfalls wird ein "Programm" thread Mülleinsammlungs ist!

171 assert(Thread::current()->is_VM_thread(), "Should be VM thread"); 

Wir sind eine gleichzeitige Sammler, so dass wir besser gleichzeitig geplant werden!

172 assert(GCLockerInvokesConcurrent || ExplicitGCInvokesConcurrent, "Unexpected"); 
    173 

Greifen Sie den Heap (der das GCCause-Objekt enthält).

174 GenCollectedHeap* gch = GenCollectedHeap::heap(); 

Überprüfen Sie, ob wir einen Vordergrund „jungen“ Sammlung

175 if (_gc_count_before == gch->total_collections()) { 
    176  // The "full" of do_full_collection call below "forces" 
    177  // a collection; the second arg, 0, below ensures that 
    178  // only the young gen is collected. XXX In the future, 
    179  // we'll probably need to have something in this interface 
    180  // to say do this only if we are sure we will not bail 
    181  // out to a full collection in this attempt, but that's 
    182  // for the future. 

die Programm-Threads nicht mit dem Heap einzumischen sind, brauchen?

Holen Sie die Garbage Collection Ursache (der Grund für diese Sammlung) aus dem Heap.

185  GCCauseSetter gccs(gch, _gc_cause); 

eine vollständige Sammlung des jungen Raumes Do

Hinweis, dass seine Pässe in dem Wert der Flagge must_clear_all_soft_refs Heap , die in einem OutOfMemory Szenario auf true gesetzt worden sein, und in jedem Fall leitet die „do_full_collection“ auf nicht folgen Sie den weichen Referenzen

186  gch->do_full_collection(gch->must_clear_all_soft_refs(), 
    187        0 /* collect only youngest gen */); 

die _gc_cause eine Enumeration ist, das ist (Mutmaßungen hier) explizit gelöscht (unter dem „Recht auf _allocation_failure im ersten Versuch OutOfMemoryError und _last_ditch_collection danach nicht zu vermeiden (um zu versuchen, vorübergehenden Müll zu sammeln)

Ein kurzer Blick in den memory "heap" module dass in do_full_collection zeigt welche do_collection weiche Referenzen nennt "Bedingungen) mit der Linie

480 ClearedAllSoftRefs casr(do_clear_all_soft_refs, collector_policy()); 

--- Original-Beitrag für die folgt, die über schwache Verweise lernen wollen ---

In der Mark und Sweep Algorithmus, Soft-Referenzen nicht gefolgt von dem Haupt-Thread (und somit nicht markiert, es sei denn, ein anderer Zweig könnte es durch nicht weiche Referenzen erreichen.

Im Kopieralgorithmus werden weiche Referenzen von Objekten auf nicht kopiert (auch wenn sie nicht durch eine andere nicht weiche Referenz erreicht werden).

Wenn Sie dem Referenznetz aus dem Hauptthread der Ausführung folgen, werden weiche Referenzen nicht gefolgt. Dadurch können ihre Objekte als Garbage Collection erfasst werden, so als ob sie keine Referenzen hätten, die auf sie verweisen.

Es ist wichtig zu erwähnen, dass Soft-Referenzen fast nie isoliert verwendet werden. Sie werden normalerweise in Objekten verwendet, in denen das Design mehrere Verweise auf das Objekt haben soll, aber nur eine Referenz muss gelöscht werden, um die Garbage Collection auszulösen (zur einfachen Pflege des Containers oder zur Laufzeit, ohne dass teure Referenzen gesucht werden müssen). .

+1

Es klingt, als würden Sie schwache Referenzen und keine weichen Referenzen beschreiben. –

+0

@DaveL. Das ist genug für mich heute Abend. Wenn Sie spezifischere Antworten benötigen, sind diese wahrscheinlich in der JVM-Code-Referenz oben in der Nähe. –

+0

Edwin, danke für die Recherche. Wenn ich das richtig verstehe, deutet dies darauf hin, dass alle weichen Referenzen in einem OutOfMemory-Szenario gelöscht werden, was sicherlich Sinn macht. Die Frage ist dann wird es noch einige klar, auch wenn diese Flagge nicht sinnvoll ist. Die HotSpot FAQ und Jeremy Mansons Blog zeigen einen Algorithmus dafür an. –

3

Unabhängig davon, ob Sie auf eine bestimmte Strategie vertrauen, ist Ihre Software unzuverlässig, da sich jede JVM-Implementierung unterscheiden kann. Selbst bei einer bestimmten JVM kann eine andere Konfiguration die genaue Strategie ändern und die Software beschädigen. Kurz gesagt, es ist ein Fehler, sich auf eine bestimmte Strategie zu verlassen.

Welche Art von Ressource verwaltet Ihr Cache? Wenn es sich um ein reines Heap-Objekt handelt, sollte die Strategie keine Rolle spielen. Das Verwenden einer ReferenceQueue kann jedoch dazu beitragen, dass Sie benachrichtigt werden, wenn eine SoftReference gelöscht wird.

Wenn der Ressourcentyp nicht nur ein Heap-allokiertes Objekt ist, müssen Sie Ihre Benutzer auffordern, eine explizite Freigabe-Methode aufzurufen, z. B. Closeable.close(). Um sich vor "vergessenen" Aufrufen dieser Veröffentlichungsmethode zu schützen, können Sie eine finalize() -Methode implementieren, aber achten Sie auf deren Nebenwirkungen. Für weitere Informationen zu diesem Thema empfehle ich "Punkt 7: Finalizer vermeiden" aus Joshua Blochs "Effective Java (2nd Edition)".

+1

Dennoch ist es manchmal hilfreich zu verstehen, wie Ihre JVM implementiert ist und wie sie sich verhält. –

+0

Ja, natürlich. Verlassen Sie sich nicht darauf. ;-) –

2

Gefunden eine Information in einem HotSpot FAQ, die veraltet sein können: http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#gc_softrefs

Was bestimmt, wann leise referenzierte Objekte gespült werden?

Beginnend mit 1.3.1 bleiben weich erreichbare Objekte für einige Zeit nach der letzten Zeit, zu der sie referenziert wurden. Der Standardwert ist eine Sekunde Lebensdauer pro freiem Megabyte im Heap. Dieser Wert kann mit dem Flag -XX: SoftRefLRUPolicyMSPerMB angepasst werden, das ganzzahlige Werte für Millisekunden akzeptiert. Zum Beispiel, um den Wert von einer Sekunde zu ändern, bis 2,5 Sekunden mit diesem Flag:

-XX: SoftRefLRUPolicyMSPerMB = 2.500

Die Java-VM HotSpot Server verwendet die maximal mögliche Zwischenspeichergröße (als mit dem eingestellten Option -Xmx), um den verbleibenden freien Speicherplatz zu berechnen.

Die Java Hotspot-Client-VM verwendet die aktuelle Heap-Größe, um den freien Speicherbereich zu berechnen.

Dies bedeutet, dass die allgemeine Tendenz für den Server ist VM die Heap anstatt bündig weiche Referenzen zu wachsen, und -Xmx hat daher einen signifikanten Effekt auf, wenn weiche Referenzen sind Müll gesammelt.

Auf der anderen Seite wird die Client-VM eine größere Tendenz haben, weiche Referenzen zu leeren, anstatt den Heap zu vergrößern.

Das oben beschriebene Verhalten gilt für Versionen 1.3.1 bis Java SE 6 der Java HotSpot-VMs. Dieses Verhalten ist jedoch nicht Bestandteil der Spezifikation VM und kann in zukünftigen Versionen geändert werden. Es ist nicht garantiert, dass das Flag -XX: SoftRefLRUPolicyMSPerMB in einer bestimmten Version vorhanden ist.

Vor Version 1.3.1 löschten die Java HotSpot-VMs Softreferenzen , wenn sie gefunden wurden.

Noch Detail unter: http://jeremymanson.blogspot.com/2009/07/how-hotspot-decides-to-clear_07.html (mit freundlicher Genehmigung von MiserableVariable Kommentar)

0

Brainstorming einfach. Wenn Sie möchten, dass Ihr Cache vor dem anderen Cache gelöscht wird, können Sie die beiden möglicherweise verknüpfen? Vielleicht indem Sie einen starken Bezug zu den Einträgen im zweiten Cache behalten und nur diese Referenzen freigeben, wenn die Mitglieder Ihres eigenen Caches gelöscht werden?

Scheint verschachtelt. Ich würde mich wahrscheinlich darauf beschränken, einfach zu akzeptieren, dass beide Caches genau das sind, ein Cache. Cache-Misses könne, um die Leistung schmerzhaft sein, aber zumindest Ihre Software nicht eine gewundene Cache-Management-Strategie hat.

2

Nicht, dass dies maßgebend ist aber SoftReference in Wut mit Ich habe noch nie gesehen, wie sie VM statt zunehmender VM Größe zu spülen. Eigentlich habe ich angenommen, irgendwie, dass der Fall, und das Design ist sehr viel auf, dass abhängig zu sein. Ich hatte die gleichen -ms und -mx aber das sollte nicht wichtig sein.

Aber ich kann keine Spezifikation finden, die tatsächlich besagt, dass dies erforderlich ist. This Blog scheint sehr ins Detail zu gehen, wie SoftReferences gespült werden. Von einem schnellen Lesen scheint es tatsächlich wie sie können gelöscht werden, auch wenn anderer Speicher verfügbar ist.

+0

Warum der Downvote :( –

Verwandte Themen