Summary
The UCO constructor callbacks (nctor_0_uco, nctor_1_uco, etc.) generated by TypeMapAssemblyEmitter.EmitUcoConstructor lack exception handling. If the activation constructor throws, the exception crosses the JNI boundary unhandled, causing a SIGABRT.
Current behavior
// Generated nctor_0_uco — no try/catch
public static void nctor_0_uco(nint jnienv, nint self)
{
if (!JniEnvironment.WithinNewObjectScope && !JavaPeerProxy.ShouldSkipActivation(self))
{
var obj = (MyType)RuntimeHelpers.GetUninitializedObject(typeof(MyType));
obj..ctor(ref jniRef, JniObjectReferenceOptions.Copy);
// If ctor throws → unhandled → SIGABRT
}
}
Expected behavior
Should mirror ManagedPeer.Construct which wraps the body in:
JniEnvironment.BeginMarshalMethod(jnienv, ...)
try { ... } catch (Exception e) { __r?.OnUserUnhandledException(ref envp, e); } finally { JniEnvironment.EndMarshalMethod(ref envp); }
This ensures exceptions are properly reported through the JNI error mechanism instead of crashing the process.
Context
- Regular UCO wrappers (
n_OnCreate_uco_0, etc.) delegate to the existing n_* connector methods which already have BeginMarshalMethod/EndMarshalMethod/try-catch-finally. Only constructor UCOs are affected.
ManagedPeer.Construct (the non-trimmable equivalent) has this exception handling — see external/Java.Interop/src/Java.Interop/Java.Interop/ManagedPeer.cs:74-129.
- The IL emission code is in
src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/TypeMapAssemblyEmitter.cs in EmitUcoConstructor.
Files to modify
src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/TypeMapAssemblyEmitter.cs — emit BeginMarshalMethod/EndMarshalMethod + try/catch/finally in EmitUcoConstructor
- May need new memberrefs for
BeginMarshalMethod, EndMarshalMethod, OnUserUnhandledException
Part of #10788
Summary
The UCO constructor callbacks (
nctor_0_uco,nctor_1_uco, etc.) generated byTypeMapAssemblyEmitter.EmitUcoConstructorlack exception handling. If the activation constructor throws, the exception crosses the JNI boundary unhandled, causing a SIGABRT.Current behavior
Expected behavior
Should mirror
ManagedPeer.Constructwhich wraps the body in:JniEnvironment.BeginMarshalMethod(jnienv, ...)try { ... } catch (Exception e) { __r?.OnUserUnhandledException(ref envp, e); } finally { JniEnvironment.EndMarshalMethod(ref envp); }This ensures exceptions are properly reported through the JNI error mechanism instead of crashing the process.
Context
n_OnCreate_uco_0, etc.) delegate to the existingn_*connector methods which already haveBeginMarshalMethod/EndMarshalMethod/try-catch-finally. Only constructor UCOs are affected.ManagedPeer.Construct(the non-trimmable equivalent) has this exception handling — seeexternal/Java.Interop/src/Java.Interop/Java.Interop/ManagedPeer.cs:74-129.src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/TypeMapAssemblyEmitter.csinEmitUcoConstructor.Files to modify
src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/TypeMapAssemblyEmitter.cs— emitBeginMarshalMethod/EndMarshalMethod+ try/catch/finally inEmitUcoConstructorBeginMarshalMethod,EndMarshalMethod,OnUserUnhandledExceptionPart of #10788