2014-12-23 8 views
16

In einem multithreaded Android-Projekt Java, ich sehe Code wie folgt:Test ist ein schwacher Verweis es vor der Verwendung

final WeakReference<MyClass> myClassObjectWeakRef = 
       new WeakReference<MyClass>(aMyClassObject); 

... dann woanders:

if (myClassObjectWeakRef.get() != null) { 
    myClassObjectWeakRef.get().someMethod(); 
} 

Ich bin ziemlich Sicher gibt es eine mögliche Wettlaufsituation zwischen der Überprüfung und der Verwendung der Referenz, wenn die letzte starke Referenz auf das Objekt zwischen den beiden in einem anderen Thread freigegeben wird, aber ich kann keine Dokumentation finden oder wer/wer kann das bestätigen besser als mit einem "du hast wahrscheinlich recht".

Ich würde denken, den einzigen richtigen Weg & verwenden, um eine schwache Referenz zu testen, wird wie folgt durchgeführt:

MyClass myObject = myClassObjectWeakRef.get(); 
// we now have a strong reference, or null: standard checks apply. 
if (myObject != null) { 
    myObject.someMethod(); 
} 

ich sehr zuversichtlich bin, dass die zweite Methode ist 100% sicher, aber ich frage mich, ob es einige Java/Compiler Zucker/Magie, die ich nicht kenne, die die erste Methode sicher machen würde.

Also, ist die erste Methode 100% sicher, oder nicht?

+1

Sie haben wahrscheinlich Recht, ;-) – petey

+3

Es sollte keinen eingebauten Java/Compiler Zucker/Magie geben, um sicherzustellen, dass Methode # 1 immer funktioniert. Ihr Verständnis der Situation stimmt mit meinem Verständnis der Situation überein. – NoseKnowsAll

+0

Danke für die Frage –

Antwort

10

Die erste Methode ist definitiv unsicher. Jeder Anruf an get ist unabhängig. Es gibt nichts, was den GC davon abhält, das schwach erreichbare Objekt nach dem ersten get und vor dem zweiten zu löschen.

Die javadoc Staaten

Angenommen, der garbage collector an einem bestimmten Punkt in der Zeit bestimmt, die ein Objekt schwach erreichbar ist. Zu dieser Zeit wird alle schwachen Referenzen auf dieses Objekt und alle schwachen Referenzen auf alle anderen schwach erreichbaren Objekte, von denen das Objekt durch eine Kette von starken und weichen Referenzen erreichbar ist.

Das kann zu jedem Zeitpunkt sein. Der Aufruf von get(), der (möglicherweise) einen Verweis auf das Objekt im Stapel verschiebt, macht das Objekt vorübergehend stark erreichbar (es befindet sich auf dem Stack eines Threads), aber die Erreichbarkeit verschwindet in dem Moment, in dem der Vergleich mit null endet. Nach diesem Moment kann der GC feststellen, dass das Objekt schwach erreichbar ist und seine Referenz löschen. Sie erhalten dann eine NullPointerException.

Verwenden Sie Ihre zweite Methode. Beachten Sie jedoch, dass Sie das referenzierte Objekt stark erreichbar machen, indem Sie es einer Variablen zuweisen.