Skip to content

Commit 387bfcb

Browse files
Override CreatePeer for trimmable path, skip GetUninitializedObject
The trimmable path uses proxy.CreateInstance() which creates a fully initialized peer. Override CreatePeer instead of TryConstructPeer to bypass the GetUninitializedObject + reflection pattern. This fixes JavaCast<T> where the pre-allocated shell from GetUninitializedObject was returned with Handle == IntPtr.Zero because CreateInstance created a separate object, ignoring the shell. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 3b57107 commit 387bfcb

File tree

1 file changed

+21
-11
lines changed

1 file changed

+21
-11
lines changed

src/Mono.Android/Microsoft.Android.Runtime/JavaMarshalValueManager.cs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -505,24 +505,34 @@ void ProcessContext (HandleContext* context)
505505

506506
static readonly Type[] XAConstructorSignature = new Type [] { typeof (IntPtr), typeof (JniHandleOwnership) };
507507

508+
public override IJavaPeerable? CreatePeer (
509+
ref JniObjectReference reference,
510+
JniObjectReferenceOptions transfer,
511+
[DynamicallyAccessedMembers (Constructors)]
512+
Type? targetType)
513+
{
514+
if (RuntimeFeature.TrimmableTypeMap && _typeMap is not null && targetType is not null) {
515+
var proxy = _typeMap.GetProxyForManagedType (targetType);
516+
if (proxy is not null) {
517+
var peer = proxy.CreateInstance (reference.Handle, JniHandleOwnership.DoNotTransfer);
518+
if (peer is not null) {
519+
peer.SetJniManagedPeerState (peer.JniManagedPeerState | JniManagedPeerStates.Replaceable);
520+
JniObjectReference.Dispose (ref reference, transfer);
521+
return peer;
522+
}
523+
}
524+
}
525+
526+
return base.CreatePeer (ref reference, transfer, targetType);
527+
}
528+
508529
protected override bool TryConstructPeer (
509530
IJavaPeerable self,
510531
ref JniObjectReference reference,
511532
JniObjectReferenceOptions options,
512533
[DynamicallyAccessedMembers (Constructors)]
513534
Type type)
514535
{
515-
if (RuntimeFeature.TrimmableTypeMap) {
516-
Debug.Assert (_typeMap != null, "TrimmableTypeMap should not be null when RuntimeFeature.TrimmableTypeMap is true.");
517-
518-
if (_typeMap.TryCreatePeer (type, reference.Handle, JniHandleOwnership.DoNotTransfer)) {
519-
JniObjectReference.Dispose (ref reference, options);
520-
return true;
521-
}
522-
523-
return base.TryConstructPeer (self, ref reference, options, type);
524-
}
525-
526536
var c = type.GetConstructor (ActivationConstructorBindingFlags, null, XAConstructorSignature, null);
527537
if (c != null) {
528538
var args = new object[] {

0 commit comments

Comments
 (0)