-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Java.Interop] Prevent premature collection w/ JniInstance* #768
Conversation
7c134bb
to
ac66560
Compare
src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.cs
Show resolved
Hide resolved
Context: dotnet/android@e88cfbc While writing the commit message for dotnet/android@e88cfbcf, it occurred to me that the same fundamental scenario of: CallIntoJava (new JavaLangObjectSubclass ().Handle); // GC collects instance after `.Handle`, before `CallIntoJava()` could apply to `JniPeerMembers.JniInstanceMethods.Invoke*()` invocations: JniArgumentValue* __args = …; _members.InstanceMethods.InvokeVirtualObjectMethod (__id, this, __args); // What prevents `this` from being collected "too soon"? Address this: update `JniPeerMembers.JniInstanceMethods.Invoke*()` so that there is a `GC.KeepAlive(self)` after accessing `self.PeerReference`. This will ensure that `self` isn't collected "during" `JniEnvironment.InstanceMethods.Call*Method()` invocations. Likewise update `JniPeerMembers.JniInstanceFields.Get*Value()` and `JniPeerMembers.JniInstanceFields.Set*Value()` so that there is a `GC.KeepAlive(self)` after the `JniEnvironment.InstanceFields.*` invocation.
ac66560
to
121ad5e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
The only thing I was wondering about is
<#= returnType.ReturnType != "void" ? "var r = " : "" #>JniEnvironment.InstanceMethods.CallNonvirtual<#= returnType.JniCallType #>Method (self.PeerReference, j.JniPeerType.PeerReference, n, parameters);
line. If I understand it correctly, the j.JniPeerType
should be kept alive by self
being alive. So that should be fine.
(The Thus, |
Context: dotnet/android@e88cfbc While writing the commit message for xamarin/xamarin-android/@e88cfbcf, it occurred to me that the same fundamental scenario of: CallIntoJava (new JavaLangObjectSubclass ().Handle); // GC collects instance after `.Handle`, before `CallIntoJava()` could apply to `JniPeerMembers.JniInstanceMethods.Invoke*()` invocations: JniArgumentValue* __args = …; _members.InstanceMethods.InvokeVirtualObjectMethod (__id, this, __args); // What prevents `this` from being collected "too soon"? Address this: update `JniPeerMembers.JniInstanceMethods.Invoke*()` so that there is a `GC.KeepAlive(self)` after accessing `self.PeerReference`. This will ensure that `self` isn't collected "during" `JniEnvironment.InstanceMethods.Call*Method()` invocations. Likewise update `JniPeerMembers.JniInstanceFields.Get*Value()` and `JniPeerMembers.JniInstanceFields.Set*Value()` so that there is a `GC.KeepAlive(self)` after the `JniEnvironment.InstanceFields.*` invocation.
Context: dotnet/android@e88cfbc While writing the commit message for xamarin/xamarin-android/@e88cfbcf, it occurred to me that the same fundamental scenario of: CallIntoJava (new JavaLangObjectSubclass ().Handle); // GC collects instance after `.Handle`, before `CallIntoJava()` could apply to `JniPeerMembers.JniInstanceMethods.Invoke*()` invocations: JniArgumentValue* __args = …; _members.InstanceMethods.InvokeVirtualObjectMethod (__id, this, __args); // What prevents `this` from being collected "too soon"? Address this: update `JniPeerMembers.JniInstanceMethods.Invoke*()` so that there is a `GC.KeepAlive(self)` after accessing `self.PeerReference`. This will ensure that `self` isn't collected "during" `JniEnvironment.InstanceMethods.Call*Method()` invocations. Likewise update `JniPeerMembers.JniInstanceFields.Get*Value()` and `JniPeerMembers.JniInstanceFields.Set*Value()` so that there is a `GC.KeepAlive(self)` after the `JniEnvironment.InstanceFields.*` invocation.
Context: dotnet/android@e88cfbc
While writing the commit message for xamarin/xamarin-android/@e88cfbcf,
it occurred to me that the same fundamental scenario of:
could apply to
JniPeerMembers.JniInstanceMethods.Invoke*()
invocations:
Address this: update
JniPeerMembers.JniInstanceMethods.Invoke*()
so that there is a
GC.KeepAlive(self)
after accessingself.PeerReference
. This will ensure thatself
isn't collected"during"
JniEnvironment.InstanceMethods.Call*Method()
invocations.Likewise update
JniPeerMembers.JniInstanceFields.Get*Value()
andJniPeerMembers.JniInstanceFields.Set*Value()
so that there is aGC.KeepAlive(self)
after theJniEnvironment.InstanceFields.*
invocation.