Skip to content

Commit

Permalink
[Java.Interop] Improve finalization support.
Browse files Browse the repository at this point in the history
Finalizers may be run in any order, and if the process is being torn
down and/or the JavaVM/JniEnvironment has been disposed, then it's not
really valid to try to use anything that depends on them.

Unfortunately, many of the SafeHandle types DO depend on them, via
handle tracking; see commit d0b8f1d. This can result in an exception
during process teardown:

	Unhandled Exception:
	System.ObjectDisposedException: The object was used after being disposed.
	  at System.Threading.ThreadLocal`1[Java.Interop.JniEnvironment].get_Value () [0x00000] in <filename unknown>:0
	  at Java.Interop.JniEnvironment.get_RootEnvironment () [0x00006] in /Users/jon/Dropbox/Developer/Java.Interop/src/Java.Interop/Java.Interop/JniEnvironment.cs:133
	  at Java.Interop.JniEnvironment.get_Current () [0x0000d] in /Users/jon/Dropbox/Developer/Java.Interop/src/Java.Interop/Java.Interop/JniEnvironment.cs:123
	  at Java.Interop.JniMethodID.ReleaseHandle () [0x00001] in /Users/jon/Dropbox/Developer/Java.Interop/src/Java.Interop/Java.Interop/JniMethodID.cs:16
	  at System.Runtime.InteropServices.SafeHandle.Finalize () [0x00016] in /private/tmp/source-mono-mac-3.12.0-branch-32/bockbuild-mono-3.12.0-branch/profiles/mono-mac-xamarin/build-r

JniEnvironment.Current is no more, the JavaVM was Dispose()d, and
JniEnvironment.RootEnvironments was Dispose()d.

To avoid this, add a JniEnvironment.HasCurrent property, which checks
to see if JniEnvironment.Current would be valid (-ish; it just checks
JniEnvironment.current, not JniEnvironment.RootEnvironments), and
modify the *SafeHandle.ReleaseHandle() methods to only call
JavaVM.UnTrack() if JniEnvironment.HasCurrent is true.

Possible bug/something to ponder: should JavaVM actually dispose of
JniEnvironment.RootEnvironments? 99.9999% of the time, that's the
right thing to do, but if/when there's ever a JVM which allows having
more than one JavaVM within the process, ever, then this could be
problematic...
  • Loading branch information
jonpryor committed Jan 14, 2015
1 parent 6d66d5d commit 20eadd7
Show file tree
Hide file tree
Showing 5 changed files with 12 additions and 4 deletions.
4 changes: 4 additions & 0 deletions src/Java.Interop/Java.Interop/JniEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ internal List<JniLocalReference> LocalReferences {
get {return lrefs ?? (lrefs = new List<JniLocalReference> ());}
}

internal static bool HasCurrent {
get {return current != null;}
}

public static JniEnvironment Current {
get {
return current ?? RootEnvironment;
Expand Down
3 changes: 2 additions & 1 deletion src/Java.Interop/Java.Interop/JniFieldID.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ internal JniFieldID ()

protected override bool ReleaseHandle ()
{
JniEnvironment.Current.JavaVM.UnTrack (this);
if (JniEnvironment.HasCurrent)
JniEnvironment.Current.JavaVM.UnTrack (this);
return true;
}

Expand Down
3 changes: 2 additions & 1 deletion src/Java.Interop/Java.Interop/JniGlobalReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ namespace Java.Interop
public class JniGlobalReference : JniReferenceSafeHandle {
protected override bool ReleaseHandle ()
{
JniEnvironment.Current.JavaVM.JniHandleManager.DeleteGlobalReference (handle);
if (JniEnvironment.HasCurrent)
JniEnvironment.Current.JavaVM.JniHandleManager.DeleteGlobalReference (handle);
return true;
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/Java.Interop/Java.Interop/JniMethodID.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ internal JniMethodID ()

protected override bool ReleaseHandle ()
{
JniEnvironment.Current.JavaVM.UnTrack (this);
if (JniEnvironment.HasCurrent)
JniEnvironment.Current.JavaVM.UnTrack (this);
return true;
}

Expand Down
3 changes: 2 additions & 1 deletion src/Java.Interop/Java.Interop/JniWeakGlobalReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ namespace Java.Interop
public class JniWeakGlobalReference : JniReferenceSafeHandle {
protected override bool ReleaseHandle ()
{
JniEnvironment.Current.JavaVM.JniHandleManager.DeleteWeakGlobalReference (handle);
if (JniEnvironment.HasCurrent)
JniEnvironment.Current.JavaVM.JniHandleManager.DeleteWeakGlobalReference (handle);
return true;
}
}
Expand Down

0 comments on commit 20eadd7

Please sign in to comment.