I discovered that in some cases our WeakReferences appear to be still alive (Target is non-null), but they refer to objects that have been collected by the Java GC (i.e., their Handle is IntPtr.Zero). I don't think this is correct behavior. If a C# WeakReference refers to a C# object that has a Java peer then collecting the Java peer should invalidate the WeakReference.
To reproduce the issue build and run the attached project. Each time you press the button we start adding 10 new objects (kept track of via WeakReferences) to a list 10 times a second. Pressing the button again essentially starts new threads, causing objects to be created and added more quickly. We also go through the list each time to check for stale references to remove them from the list.
When a WeakReference is encountered with a non-null Target that refers to an IJavaObject with a zero Handle then an exception is thrown. When I run this test I get an exception somewhere around 1600 objects.
Created attachment 5474 [details]
This is a known issue that we're aware of, have have add a workaround in previous version (more than 6 months ago) that reduces the likelihood of witnessing this.
The workaround is to check if the returned object is ok or not. Which can be done by subclassing WeakReference. Does that work for you?
We don't have any short term plans on fixing this one.
We can add a workaround in the one case in which we know for sure that we are hitting this, but we have many other places in our large code base where we use a WeakReference that may possibly refer to a Java object. Nearly all of that code is cross-platform code, and it is not practical to modify every one of those places to use a wrapper or to have a special case for Android.