Skip to content

Commit 830f565

Browse files
committed
[Java.Interop] Do not dispose live references on return to JNI
Fixes #374 Also refactor the code generation to not create `_handle` variable when returning value to JNI. Updated the tests and their expected code strings. Example generated marshal method: using Android.OS; using Android.Views; using Java.Interop; using System; public static IntPtr n_onCreateView_Landroid_view_LayoutInflater_Landroid_view_ViewGroup_Landroid_os_Bundle_ (IntPtr __jnienv, IntPtr __this, IntPtr inflater, IntPtr container, IntPtr savedInstanceState) { JniTransition jniTransition = new JniTransition (__jnienv); JniRuntime runtime = default(JniRuntime); global::Android.Views.View view = default(global::Android.Views.View); try { runtime = JniEnvironment.Runtime; JniRuntime.JniValueManager valueManager = runtime.ValueManager; valueManager.WaitForGCBridgeProcessing (); FragmentContainer value = valueManager.GetValue<FragmentContainer> (__this); LayoutInflater value2 = valueManager.GetValue<LayoutInflater> (inflater); ViewGroup value3 = valueManager.GetValue<ViewGroup> (container); Bundle value4 = valueManager.GetValue<Bundle> (savedInstanceState); view = value.OnCreateView (value2, value3, value4); JniObjectReference value5 = (view != null) ? view.PeerReference : default(JniObjectReference); return JniEnvironment.References.NewReturnToJniRef (value5); } catch (Exception ex) when (runtime.ExceptionShouldTransitionToJni (ex)) { jniTransition.SetPendingException (ex); return default(IntPtr); } finally { if (view != null) { ((IJavaPeerable)view).DisposeUnlessReferenced (); } jniTransition.Dispose (); } IntPtr intPtr = default(IntPtr); return intPtr; }
1 parent 94c6bb5 commit 830f565

File tree

3 files changed

+35
-14
lines changed

3 files changed

+35
-14
lines changed

src/Java.Interop.Export/Tests/Java.Interop/MarshalMemberBuilderTest.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,6 @@ public void CreateMarshalFromJniMethodExpression_FuncIJavaObject ()
449449
JavaObject __mret;
450450
ExportTest __this_val;
451451
JniObjectReference __mret_ref;
452-
IntPtr __mret_handle;
453452
IntPtr __mret_rtn;
454453
455454
__envp = new JniTransition(__jnienv);
@@ -468,7 +467,6 @@ public void CreateMarshalFromJniMethodExpression_FuncIJavaObject ()
468467
{
469468
return __mret_ref = __mret.PeerReference;
470469
}
471-
__mret_handle = __mret_ref.Handle;
472470
__mret_rtn = References.NewReturnToJniRef(__mret_ref);
473471
return __mret_rtn;
474472
}
@@ -479,7 +477,14 @@ public void CreateMarshalFromJniMethodExpression_FuncIJavaObject ()
479477
}
480478
finally
481479
{
482-
JniObjectReference.Dispose(__mret_ref);
480+
if (null != __mret)
481+
{
482+
__mret.DisposeUnlessReferenced();
483+
}
484+
else
485+
{
486+
default(void);
487+
}
483488
__envp.Dispose();
484489
}
485490
}");

src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,17 @@ public override void DestroyGenericArgumentState (IJavaPeerable value, ref JniVa
590590
}
591591

592592
public override Expression CreateParameterFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize)
593+
{
594+
var r = CreateIntermediaryExpressionFromManagedExpression (context, sourceValue);
595+
596+
var h = Expression.Variable (typeof (IntPtr), sourceValue + "_handle");
597+
context.LocalVariables.Add (h);
598+
context.CreationStatements.Add (Expression.Assign (h, Expression.Property (r, "Handle")));
599+
600+
return h;
601+
}
602+
603+
Expression CreateIntermediaryExpressionFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue)
593604
{
594605
var r = Expression.Variable (typeof (JniObjectReference), sourceValue.Name + "_ref");
595606
context.LocalVariables.Add (r);
@@ -598,19 +609,19 @@ public override Expression CreateParameterFromManagedExpression (JniValueMarshal
598609
test: Expression.Equal (Expression.Constant (null), sourceValue),
599610
ifTrue: Expression.Assign (r, Expression.New (typeof (JniObjectReference))),
600611
ifFalse: Expression.Assign (r, Expression.Property (sourceValue, "PeerReference"))));
601-
context.CleanupStatements.Add (DisposeObjectReference (r));
602612

603-
var h = Expression.Variable (typeof (IntPtr), sourceValue + "_handle");
604-
context.LocalVariables.Add (h);
605-
context.CreationStatements.Add (Expression.Assign (h, Expression.Property (r, "Handle")));
606-
return h;
613+
if (typeof (IJavaPeerable).GetTypeInfo ().IsAssignableFrom (sourceValue.Type.GetTypeInfo ())) {
614+
context.CleanupStatements.Add (Expression.IfThen (
615+
test: Expression.NotEqual (Expression.Constant (null), sourceValue),
616+
ifTrue: Expression.Call (sourceValue, typeof (IJavaPeerable).GetTypeInfo ().GetDeclaredMethod ("DisposeUnlessReferenced"))));
617+
}
618+
619+
return r;
607620
}
608621

609622
public override Expression CreateReturnValueFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue)
610623
{
611-
CreateParameterFromManagedExpression (context, sourceValue, 0);
612-
var r = context.LocalVariables [sourceValue + "_ref"];
613-
return ReturnObjectReferenceToJni (context, sourceValue.Name, r);
624+
return ReturnObjectReferenceToJni (context, sourceValue.Name, CreateIntermediaryExpressionFromManagedExpression (context, sourceValue));
614625
}
615626

616627
public override Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize, Type targetType)

src/Java.Interop/Tests/Java.Interop/JniValueMarshalerContractTests.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,6 @@ protected override string GetExpectedReturnValueFromManagedExpression (string jv
591591
JniRuntime {jvm};
592592
IJavaPeerable {value};
593593
JniObjectReference {value}_ref;
594-
IntPtr {value}_handle;
595594
IntPtr {value}_rtn;
596595
597596
try
@@ -604,13 +603,19 @@ protected override string GetExpectedReturnValueFromManagedExpression (string jv
604603
{{
605604
return {value}_ref = {value}.PeerReference;
606605
}}
607-
{value}_handle = {value}_ref.Handle;
608606
{value}_rtn = References.NewReturnToJniRef({value}_ref);
609607
return {pret.Name};
610608
}}
611609
finally
612610
{{
613-
JniObjectReference.Dispose({value}_ref);
611+
if (null != __value)
612+
{{
613+
__value.DisposeUnlessReferenced();
614+
}}
615+
else
616+
{{
617+
default(void);
618+
}}
614619
}}
615620
}}";
616621
}

0 commit comments

Comments
 (0)