In a multithreaded Android project, I'm seeing code like this:
final WeakReference<MyClass> myClassObjectWeakRef = new WeakReference<MyClass>(aMyClassObject);
...then somewhere else:
if (myClassObjectWeakRef.get() != null) { myClassObjectWeakRef.get().someMethod(); }
I'm pretty sure there is a possible race condition between the check and the use of the reference, if the last strong reference to the object is released between the two in another thread, but I can't find any documentation or anyone which/who can confirm this better than with a "you're probably right".
I would think the only right way to test & use a weak reference is done like this:
MyClass myObject = myClassObjectWeakRef.get(); // we now have a strong reference, or null: standard checks apply. if (myObject != null) { myObject.someMethod(); }
I'm very confident that the second method is 100% safe, but I wonder if there is some Java/compiler sugar/magic that I don't know about, which would make the first method safe.
So, is the first method 100% safe, or not?
Weak reference objects, which do not prevent their referents from being made finalizable, finalized, and then reclaimed. Weak references are most often used to implement canonicalizing mappings. Suppose that the garbage collector determines at a certain point in time that an object is weakly reachable.
To create a Weak Reference Object, we must explicitly specify this to the JVM. Why Weak Reference Objects are used: Unlike C/C++, Java supports Dynamic Garbage Collection. This is performed when the JVM runs the Garbage Collector.
A Soft reference is eligible for collection by garbage collector, but probably won't be collected until its memory is needed. i.e. garbage collects before OutOfMemoryError . A Weak reference is a reference that does not protect a referenced object from collection by GC.
So, weakref is itself an object, when you put weak reference to an object in some container, you actually put reference to weakref object. Each ref-countable object has field to store pointer to its weakref, which is NULL until weakref to that object is actually requested.
The first method is definitely unsafe. Each call to get
is independent. There is nothing preventing the GC from clearing the weakly reachable object after the first get
and before the second.
The javadoc states
Suppose that the garbage collector determines at a certain point in time that an object is weakly reachable. At that time it will atomically clear all weak references to that object and all weak references to any other weakly-reachable objects from which that object is reachable through a chain of strong and soft references.
That can be at any point in time. Calling get()
, which (potentially) pushes a reference to the object on the stack temporarily makes the object strongly reachable (it's on a thread's stack), but that reach-ability disappears the moment the comparison with null
finishes. After that moment, the GC can determine that the object is weakly reachable and clear its reference. You'd then get a NullPointerException
.
Use your second method. But note that by assigning it to a variable, you are making the referenced object strongly reachable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With