diff --git a/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteCtorWithStringOverload.txt b/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteCtorWithStringOverload.txt index eef2acbb8..44dd780e6 100644 --- a/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteCtorWithStringOverload.txt +++ b/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteCtorWithStringOverload.txt @@ -17,6 +17,7 @@ _members.InstanceMethods.FinishCreateInstance (__id, this, __args); } finally { JNIEnv.DeleteLocalRef (native_mystring); + global::System.GC.KeepAlive (mystring); } } @@ -38,6 +39,7 @@ _members.InstanceMethods.FinishCreateInstance (__id, this, __args); } finally { JNIEnv.DeleteLocalRef (native_mystring); + global::System.GC.KeepAlive (mystring); } } diff --git a/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteKotlinUnsignedArrayTypeMethodsClass.txt b/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteKotlinUnsignedArrayTypeMethodsClass.txt index 6dc50ca2f..089260b54 100644 --- a/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteKotlinUnsignedArrayTypeMethodsClass.txt +++ b/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteKotlinUnsignedArrayTypeMethodsClass.txt @@ -27,6 +27,7 @@ public partial class MyClass { JNIEnv.CopyArray (native_value, value); JNIEnv.DeleteLocalRef (native_value); } + global::System.GC.KeepAlive (value); } } @@ -46,6 +47,7 @@ public partial class MyClass { JNIEnv.CopyArray (native_value, value); JNIEnv.DeleteLocalRef (native_value); } + global::System.GC.KeepAlive (value); } } @@ -65,6 +67,7 @@ public partial class MyClass { JNIEnv.CopyArray (native_value, value); JNIEnv.DeleteLocalRef (native_value); } + global::System.GC.KeepAlive (value); } } @@ -84,6 +87,7 @@ public partial class MyClass { JNIEnv.CopyArray (native_value, value); JNIEnv.DeleteLocalRef (native_value); } + global::System.GC.KeepAlive (value); } } diff --git a/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteKotlinUnsignedArrayTypePropertiesClass.txt b/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteKotlinUnsignedArrayTypePropertiesClass.txt index 3f2241de6..e500b02aa 100644 --- a/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteKotlinUnsignedArrayTypePropertiesClass.txt +++ b/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteKotlinUnsignedArrayTypePropertiesClass.txt @@ -36,6 +36,7 @@ public partial class MyClass { JNIEnv.CopyArray (native_value, value); JNIEnv.DeleteLocalRef (native_value); } + global::System.GC.KeepAlive (value); } } } @@ -65,6 +66,7 @@ public partial class MyClass { JNIEnv.CopyArray (native_value, value); JNIEnv.DeleteLocalRef (native_value); } + global::System.GC.KeepAlive (value); } } } @@ -94,6 +96,7 @@ public partial class MyClass { JNIEnv.CopyArray (native_value, value); JNIEnv.DeleteLocalRef (native_value); } + global::System.GC.KeepAlive (value); } } } @@ -123,6 +126,7 @@ public partial class MyClass { JNIEnv.CopyArray (native_value, value); JNIEnv.DeleteLocalRef (native_value); } + global::System.GC.KeepAlive (value); } } } diff --git a/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1-NRT/WriteCtorWithStringOverload.txt b/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1-NRT/WriteCtorWithStringOverload.txt index 342763a13..3b510c039 100644 --- a/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1-NRT/WriteCtorWithStringOverload.txt +++ b/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1-NRT/WriteCtorWithStringOverload.txt @@ -17,6 +17,7 @@ _members.InstanceMethods.FinishCreateInstance (__id, this, __args); } finally { JNIEnv.DeleteLocalRef (native_mystring); + global::System.GC.KeepAlive (mystring); } } @@ -38,6 +39,7 @@ _members.InstanceMethods.FinishCreateInstance (__id, this, __args); } finally { JNIEnv.DeleteLocalRef (native_mystring); + global::System.GC.KeepAlive (mystring); } } diff --git a/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteCtorWithStringOverload.txt b/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteCtorWithStringOverload.txt index eef2acbb8..44dd780e6 100644 --- a/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteCtorWithStringOverload.txt +++ b/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteCtorWithStringOverload.txt @@ -17,6 +17,7 @@ _members.InstanceMethods.FinishCreateInstance (__id, this, __args); } finally { JNIEnv.DeleteLocalRef (native_mystring); + global::System.GC.KeepAlive (mystring); } } @@ -38,6 +39,7 @@ _members.InstanceMethods.FinishCreateInstance (__id, this, __args); } finally { JNIEnv.DeleteLocalRef (native_mystring); + global::System.GC.KeepAlive (mystring); } } diff --git a/tests/generator-Tests/expected.ji/Adapters/Xamarin.Test.AbsSpinner.cs b/tests/generator-Tests/expected.ji/Adapters/Xamarin.Test.AbsSpinner.cs index 9af7c4cee..f74802047 100644 --- a/tests/generator-Tests/expected.ji/Adapters/Xamarin.Test.AbsSpinner.cs +++ b/tests/generator-Tests/expected.ji/Adapters/Xamarin.Test.AbsSpinner.cs @@ -83,6 +83,7 @@ static void n_SetAdapter_Lxamarin_test_SpinnerAdapter_ (IntPtr jnienv, IntPtr na __args [0] = new JniArgumentValue ((value == null) ? IntPtr.Zero : ((global::Java.Lang.Object) value).Handle); _members.InstanceMethods.InvokeVirtualVoidMethod (__id, this, __args); } finally { + global::System.GC.KeepAlive (value); } } } @@ -126,6 +127,7 @@ public AbsSpinnerInvoker (IntPtr handle, JniHandleOwnership transfer) : base (ha _members.InstanceMethods.InvokeAbstractVoidMethod (__id, this, __args); } finally { JNIEnv.DeleteLocalRef (native_value); + global::System.GC.KeepAlive (value); } } } diff --git a/tests/generator-Tests/expected.ji/Adapters/Xamarin.Test.AdapterView.cs b/tests/generator-Tests/expected.ji/Adapters/Xamarin.Test.AdapterView.cs index 0377b29fd..f1fcacb6d 100644 --- a/tests/generator-Tests/expected.ji/Adapters/Xamarin.Test.AdapterView.cs +++ b/tests/generator-Tests/expected.ji/Adapters/Xamarin.Test.AdapterView.cs @@ -110,6 +110,7 @@ public AdapterViewInvoker (IntPtr handle, JniHandleOwnership transfer) : base (h _members.InstanceMethods.InvokeAbstractVoidMethod (__id, this, __args); } finally { JNIEnv.DeleteLocalRef (native_value); + global::System.GC.KeepAlive (value); } } } diff --git a/tests/generator-Tests/expected.ji/Core_Jar2Xml/Android.Text.SpannableString.cs b/tests/generator-Tests/expected.ji/Core_Jar2Xml/Android.Text.SpannableString.cs index 2f96f1fe1..d5c71261c 100644 --- a/tests/generator-Tests/expected.ji/Core_Jar2Xml/Android.Text.SpannableString.cs +++ b/tests/generator-Tests/expected.ji/Core_Jar2Xml/Android.Text.SpannableString.cs @@ -49,6 +49,7 @@ public unsafe SpannableString (global::Java.Lang.ICharSequence source) _members.InstanceMethods.FinishCreateInstance (__id, this, __args); } finally { JNIEnv.DeleteLocalRef (native_source); + global::System.GC.KeepAlive (source); } } @@ -70,6 +71,7 @@ public unsafe SpannableString (string source) _members.InstanceMethods.FinishCreateInstance (__id, this, __args); } finally { JNIEnv.DeleteLocalRef (native_source); + global::System.GC.KeepAlive (source); } } @@ -102,6 +104,7 @@ static int n_GetSpanFlags_Ljava_lang_Object_ (IntPtr jnienv, IntPtr native__this var __rm = _members.InstanceMethods.InvokeVirtualInt32Method (__id, this, __args); return (global::Android.Text.SpanTypes) __rm; } finally { + global::System.GC.KeepAlive (what); } } diff --git a/tests/generator-Tests/expected.ji/Core_Jar2Xml/Android.Text.SpannableStringInternal.cs b/tests/generator-Tests/expected.ji/Core_Jar2Xml/Android.Text.SpannableStringInternal.cs index d1fd6eb38..5de9ca791 100644 --- a/tests/generator-Tests/expected.ji/Core_Jar2Xml/Android.Text.SpannableStringInternal.cs +++ b/tests/generator-Tests/expected.ji/Core_Jar2Xml/Android.Text.SpannableStringInternal.cs @@ -60,6 +60,7 @@ static int n_GetSpanFlags_Ljava_lang_Object_ (IntPtr jnienv, IntPtr native__this var __rm = _members.InstanceMethods.InvokeVirtualInt32Method (__id, this, __args); return (global::Android.Text.SpanTypes) __rm; } finally { + global::System.GC.KeepAlive (p0); } } diff --git a/tests/generator-Tests/expected.ji/Core_Jar2Xml/Android.Views.View.cs b/tests/generator-Tests/expected.ji/Core_Jar2Xml/Android.Views.View.cs index 5ac088ea9..0be44ac2c 100644 --- a/tests/generator-Tests/expected.ji/Core_Jar2Xml/Android.Views.View.cs +++ b/tests/generator-Tests/expected.ji/Core_Jar2Xml/Android.Views.View.cs @@ -176,6 +176,7 @@ public virtual unsafe void SetOnClickListener (global::Android.Views.View.IOnCli __args [0] = new JniArgumentValue ((l == null) ? IntPtr.Zero : ((global::Java.Lang.Object) l).Handle); _members.InstanceMethods.InvokeVirtualVoidMethod (__id, this, __args); } finally { + global::System.GC.KeepAlive (l); } } @@ -206,6 +207,7 @@ public virtual unsafe void SetOn123Listener (global::Android.Views.View.IOnClick __args [0] = new JniArgumentValue ((l == null) ? IntPtr.Zero : ((global::Java.Lang.Object) l).Handle); _members.InstanceMethods.InvokeVirtualVoidMethod (__id, this, __args); } finally { + global::System.GC.KeepAlive (l); } } @@ -238,6 +240,7 @@ public virtual unsafe void AddTouchables (global::System.Collections.Generic.ILi _members.InstanceMethods.InvokeVirtualVoidMethod (__id, this, __args); } finally { JNIEnv.DeleteLocalRef (native_views); + global::System.GC.KeepAlive (views); } } diff --git a/tests/generator-Tests/expected.ji/GenericArguments/Com.Google.Android.Exoplayer.Drm.FrameworkMediaDrm.cs b/tests/generator-Tests/expected.ji/GenericArguments/Com.Google.Android.Exoplayer.Drm.FrameworkMediaDrm.cs index c0ddc30eb..7ebb23b86 100644 --- a/tests/generator-Tests/expected.ji/GenericArguments/Com.Google.Android.Exoplayer.Drm.FrameworkMediaDrm.cs +++ b/tests/generator-Tests/expected.ji/GenericArguments/Com.Google.Android.Exoplayer.Drm.FrameworkMediaDrm.cs @@ -58,6 +58,7 @@ public unsafe void SetOnEventListener (global::Com.Google.Android.Exoplayer.Drm. __args [0] = new JniArgumentValue ((p0 == null) ? IntPtr.Zero : ((global::Java.Lang.Object) p0).Handle); _members.InstanceMethods.InvokeAbstractVoidMethod (__id, this, __args); } finally { + global::System.GC.KeepAlive (p0); } } diff --git a/tests/generator-Tests/expected.ji/NestedTypes/Xamarin.Test.NotificationCompatBase.cs b/tests/generator-Tests/expected.ji/NestedTypes/Xamarin.Test.NotificationCompatBase.cs index e1d8ae2ee..a74430f02 100644 --- a/tests/generator-Tests/expected.ji/NestedTypes/Xamarin.Test.NotificationCompatBase.cs +++ b/tests/generator-Tests/expected.ji/NestedTypes/Xamarin.Test.NotificationCompatBase.cs @@ -186,6 +186,7 @@ public unsafe InstanceInner (global::Xamarin.Test.NotificationCompatBase __self) SetHandle (__r.Handle, JniHandleOwnership.TransferLocalRef); _members.InstanceMethods.FinishCreateInstance (__id, this, __args); } finally { + global::System.GC.KeepAlive (__self); } } diff --git a/tests/generator-Tests/expected.ji/NormalMethods/Xamarin.Test.SomeObject.cs b/tests/generator-Tests/expected.ji/NormalMethods/Xamarin.Test.SomeObject.cs index 19cca3989..be3160fcf 100644 --- a/tests/generator-Tests/expected.ji/NormalMethods/Xamarin.Test.SomeObject.cs +++ b/tests/generator-Tests/expected.ji/NormalMethods/Xamarin.Test.SomeObject.cs @@ -47,6 +47,7 @@ public unsafe SomeObject (global::Java.Lang.Class c) SetHandle (__r.Handle, JniHandleOwnership.TransferLocalRef); _members.InstanceMethods.FinishCreateInstance (__id, this, __args); } finally { + global::System.GC.KeepAlive (c); } } @@ -109,6 +110,8 @@ static int n_Handle_Ljava_lang_Object_Ljava_lang_Throwable_ (IntPtr jnienv, IntP var __rm = _members.InstanceMethods.InvokeVirtualInt32Method (__id, this, __args); return __rm; } finally { + global::System.GC.KeepAlive (o); + global::System.GC.KeepAlive (t); } } @@ -255,6 +258,7 @@ public virtual unsafe void VoidMethodWithParams (string astring, int anint, glob _members.InstanceMethods.InvokeVirtualVoidMethod (__id, this, __args); } finally { JNIEnv.DeleteLocalRef (native_astring); + global::System.GC.KeepAlive (anObject); } } @@ -318,6 +322,7 @@ public virtual unsafe void ArrayListTest (global::System.Collections.Generic.ILi _members.InstanceMethods.InvokeVirtualVoidMethod (__id, this, __args); } finally { JNIEnv.DeleteLocalRef (native_p0); + global::System.GC.KeepAlive (p0); } } diff --git a/tests/generator-Tests/expected.ji/NormalProperties/Xamarin.Test.SomeObject.cs b/tests/generator-Tests/expected.ji/NormalProperties/Xamarin.Test.SomeObject.cs index fea7ba757..35e615255 100644 --- a/tests/generator-Tests/expected.ji/NormalProperties/Xamarin.Test.SomeObject.cs +++ b/tests/generator-Tests/expected.ji/NormalProperties/Xamarin.Test.SomeObject.cs @@ -210,6 +210,7 @@ public override unsafe int SomeInteger { __args [0] = new JniArgumentValue ((value == null) ? IntPtr.Zero : ((global::Java.Lang.Object) value).Handle); _members.InstanceMethods.InvokeAbstractVoidMethod (__id, this, __args); } finally { + global::System.GC.KeepAlive (value); } } } diff --git a/tests/generator-Tests/expected.ji/ParameterXPath/Xamarin.Test.A.cs b/tests/generator-Tests/expected.ji/ParameterXPath/Xamarin.Test.A.cs index 61c229d49..7d0387df5 100644 --- a/tests/generator-Tests/expected.ji/ParameterXPath/Xamarin.Test.A.cs +++ b/tests/generator-Tests/expected.ji/ParameterXPath/Xamarin.Test.A.cs @@ -60,6 +60,7 @@ public virtual unsafe void SetA (global::Java.Lang.Object adapter) _members.InstanceMethods.InvokeVirtualVoidMethod (__id, this, __args); } finally { JNIEnv.DeleteLocalRef (native_adapter); + global::System.GC.KeepAlive (adapter); } } @@ -92,6 +93,7 @@ public virtual unsafe void ListTest (global::System.Collections.Generic.IList (__rm.Handle, JniHandleOwnership.TransferLocalRef); } finally { JNIEnv.DeleteLocalRef (native_value); + global::System.GC.KeepAlive (value); } } diff --git a/tests/generator-Tests/expected.ji/java.lang.Enum/Java.Lang.Enum.cs b/tests/generator-Tests/expected.ji/java.lang.Enum/Java.Lang.Enum.cs index 648ab525b..93587873d 100644 --- a/tests/generator-Tests/expected.ji/java.lang.Enum/Java.Lang.Enum.cs +++ b/tests/generator-Tests/expected.ji/java.lang.Enum/Java.Lang.Enum.cs @@ -44,6 +44,7 @@ public unsafe int CompareTo (global::Java.Lang.Object o) return __rm; } finally { JNIEnv.DeleteLocalRef (native_o); + global::System.GC.KeepAlive (o); } } diff --git a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/JavaInteropCodeGenerator.cs b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/JavaInteropCodeGenerator.cs index 52d2788ae..305b908c8 100644 --- a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/JavaInteropCodeGenerator.cs +++ b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/JavaInteropCodeGenerator.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Linq; using Mono.Options; namespace MonoDroid.Generation { @@ -130,6 +131,8 @@ internal override void WriteConstructorBody (Ctor ctor, string indent, System.Co writer.WriteLine ("{0}}} finally {{", indent); foreach (string cleanup in call_cleanup) writer.WriteLine ("{0}\t{1}", indent, cleanup); + foreach (var p in ctor.Parameters.Where (GenerateKeepAlive)) + writer.WriteLine ($"{indent}\tglobal::System.GC.KeepAlive ({opt.GetSafeIdentifier (p.Name)});"); writer.WriteLine ("{0}}}", indent); } @@ -182,9 +185,38 @@ internal override void WriteMethodBody (Method method, string indent, GenBase ty writer.WriteLine ("{0}}} finally {{", indent); foreach (string cleanup in method.Parameters.GetCallCleanup (opt)) writer.WriteLine ("{0}\t{1}", indent, cleanup); + foreach (var p in method.Parameters.Where (GenerateKeepAlive)) + writer.WriteLine ($"{indent}\tglobal::System.GC.KeepAlive ({opt.GetSafeIdentifier (p.Name)});"); + writer.WriteLine ("{0}}}", indent); } + bool GenerateKeepAlive (Parameter p) + { + if (p.Symbol.IsEnum) + return false; + + return p.Type switch { + "bool" => false, + "sbyte" => false, + "char" => false, + "double" => false, + "float" => false, + "int" => false, + "long" => false, + "short" => false, + "uint" => false, + "ushort" => false, + "ulong" => false, + "byte" => false, + "ubyte" => false, // Not a C# type, but we will see it from Kotlin unsigned types support + "string" => false, + "java.lang.String" => false, + "Android.Graphics.Color" => false, + _ => true + }; + } + internal override void WriteFieldIdField (Field field, string indent) { // No field id_ field required