diff --git a/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteKotlinUnsignedArrayTypeMethodsClass.txt b/tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteKotlinUnsignedArrayTypeMethodsClass.txt index e5e3cc232..6f69484cd 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 64abe3ca5..b8fd49fed 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/expected.ji/Adapters/Xamarin.Test.AbsSpinner.cs b/tests/generator-Tests/expected.ji/Adapters/Xamarin.Test.AbsSpinner.cs index 31e747175..2132a3ad9 100644 --- a/tests/generator-Tests/expected.ji/Adapters/Xamarin.Test.AbsSpinner.cs +++ b/tests/generator-Tests/expected.ji/Adapters/Xamarin.Test.AbsSpinner.cs @@ -89,6 +89,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); } } } @@ -137,6 +138,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 798ab1fd5..ce10d8840 100644 --- a/tests/generator-Tests/expected.ji/Adapters/Xamarin.Test.AdapterView.cs +++ b/tests/generator-Tests/expected.ji/Adapters/Xamarin.Test.AdapterView.cs @@ -124,6 +124,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 40e1a5476..24196b0ac 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 @@ -54,6 +54,7 @@ public unsafe SpannableString (global::Java.Lang.ICharSequence source) : base (I _members.InstanceMethods.FinishCreateInstance (__id, this, __args); } finally { JNIEnv.DeleteLocalRef (native_source); + global::System.GC.KeepAlive (source); } } @@ -74,6 +75,7 @@ public unsafe SpannableString (string source) : base (IntPtr.Zero, JniHandleOwne _members.InstanceMethods.FinishCreateInstance (__id, this, __args); } finally { JNIEnv.DeleteLocalRef (native_source); + global::System.GC.KeepAlive (source); } } @@ -106,6 +108,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 c8b04875b..3a8cfa38e 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 @@ -66,6 +66,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 0d6077eec..35d48977c 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 @@ -181,6 +181,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); } } @@ -211,6 +212,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); } } @@ -243,6 +245,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 5aed0be99..7c208eb60 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 @@ -63,6 +63,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 b3892c133..aa3dac3a0 100644 --- a/tests/generator-Tests/expected.ji/NestedTypes/Xamarin.Test.NotificationCompatBase.cs +++ b/tests/generator-Tests/expected.ji/NestedTypes/Xamarin.Test.NotificationCompatBase.cs @@ -202,6 +202,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 60c814623..2d6ee34ac 100644 --- a/tests/generator-Tests/expected.ji/NormalMethods/Xamarin.Test.SomeObject.cs +++ b/tests/generator-Tests/expected.ji/NormalMethods/Xamarin.Test.SomeObject.cs @@ -52,6 +52,7 @@ public unsafe SomeObject (global::Java.Lang.Class c) : base (IntPtr.Zero, JniHan SetHandle (__r.Handle, JniHandleOwnership.TransferLocalRef); _members.InstanceMethods.FinishCreateInstance (__id, this, __args); } finally { + global::System.GC.KeepAlive (c); } } @@ -114,6 +115,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); } } @@ -260,6 +263,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); } } @@ -323,6 +327,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 d3eab10c0..dd336a8a0 100644 --- a/tests/generator-Tests/expected.ji/NormalProperties/Xamarin.Test.SomeObject.cs +++ b/tests/generator-Tests/expected.ji/NormalProperties/Xamarin.Test.SomeObject.cs @@ -230,6 +230,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 7b5cd32f7..ab206c2b6 100644 --- a/tests/generator-Tests/expected.ji/ParameterXPath/Xamarin.Test.A.cs +++ b/tests/generator-Tests/expected.ji/ParameterXPath/Xamarin.Test.A.cs @@ -66,6 +66,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); } } @@ -98,6 +99,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 a5ae1dc7e..3370de241 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 @@ -50,6 +50,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.ObjectModel/Parameter.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Parameter.cs index 120f728d2..1fc7eb870 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Parameter.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Parameter.cs @@ -276,6 +276,32 @@ public bool Validate (CodeGenerationOptions opt, GenericParameterDefinitionList return true; } + public bool ShouldGenerateKeepAlive () + { + if (Symbol.IsEnum) + return false; + + return 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 + }; + } + public ISymbol Symbol => sym; } } diff --git a/tools/generator/SourceWriters/BoundConstructor.cs b/tools/generator/SourceWriters/BoundConstructor.cs index d52f52ef5..5ec69de81 100644 --- a/tools/generator/SourceWriters/BoundConstructor.cs +++ b/tools/generator/SourceWriters/BoundConstructor.cs @@ -76,6 +76,10 @@ protected override void WriteBody (CodeWriter writer) var call_cleanup = constructor.Parameters.GetCallCleanup (opt); foreach (string cleanup in call_cleanup) writer.WriteLine (cleanup); + + foreach (var p in constructor.Parameters.Where (para => para.ShouldGenerateKeepAlive ())) + writer.WriteLine ($"global::System.GC.KeepAlive ({opt.GetSafeIdentifier (p.Name)});"); + writer.Unindent (); writer.WriteLine ("}"); diff --git a/tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs b/tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs index 06928531c..3d96941d3 100644 --- a/tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs +++ b/tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs @@ -264,6 +264,9 @@ public static void AddMethodBody (List body, Method method, CodeGenerati foreach (string cleanup in method.Parameters.GetCallCleanup (opt)) body.Add ("\t" + cleanup); + foreach (var p in method.Parameters.Where (para => para.ShouldGenerateKeepAlive ())) + body.Add ($"\tglobal::System.GC.KeepAlive ({opt.GetSafeIdentifier (p.Name)});"); + body.Add ("}"); }