dotnet / dotnet/android

Explore ManagedPeer compatibility for trimmable typemap apps

Open
#11,635 0 comments 0 reactions 1 assignee Claimed by @simonrozsival View on GitHub
needs-triage
Dominant language
C#
Stars
2.1k
Forks
579
Avg merge
1d 20h
Merged PRs (30d)
257

Description

## Context

The trimmable typemap runtime intentionally removes `net.dot.jni.ManagedPeer` from `java_runtime_trimmable.jar` and sets `Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration=false`. Trimmable-generated Java/proxy/native-registration code should use generated UCO/proxy paths such as `mono.android.Runtime.registerNatives(Class)` instead of the legacy dynamic Java.Interop bridge:

```java
net.dot.jni.ManagedPeer.registerNativeMembers(Class nativeClass, String methods)
net.dot.jni.ManagedPeer.construct(Object self, String constructorSignature, Object... args)
```

This is desirable for app size and trim/AOT safety, but old generated or handwritten Java bytecode can still reference `ManagedPeer`, which would fail in trimmable apps with `NoClassDefFoundError`.

## Question

Should we add an explicit opt-in compatibility path for trimmable apps that still package Java bytecode referencing `net.dot.jni.ManagedPeer`?

## Possible shape

Default behavior should stay strict:

- Do not package `ManagedPeer.class` in trimmable apps.
- Keep `ManagedPeerNativeRegistration=false`.
- Ideally detect Java bytecode references to `net/dot/jni/ManagedPeer` at build time and fail with an actionable diagnostic.

Potential opt-in behavior, behind a property/feature switch, e.g. `AndroidEnableManagedPeerCompatibility=true`:

1. Package a tiny trimmable-compatible `net.dot.jni.ManagedPeer` shim.
2. `registerNativeMembers(Class, String)` logs a warning and remaps to generated trimmable registration, likely `mono.android.Runtime.registerNatives(Class)`.
3. `construct(Object, String, Object...)` probably remains unsupported and throws a clear error unless/until we add generated per-type constructor dispatch.
4. Build-time detection could downgrade from error to warning when the opt-in is enabled.

## Things to decide

- Is a compatibility shim worth carrying at all, even behind opt-in?
- Should `registerNativeMembers(Class, String)` ignore the legacy `methods` string and rely entirely on generated trimmable metadata?
- Should `construct(...)` always fail, or should we eventually support it through generated dispatch metadata?
- Where should detection happen: Java source scan, class/jar scan, dex scan, or a combination?
- What property name and diagnostic code should we use?

## Why this matters

We want to keep default trimmable apps free of the old dynamic bridge, but we also want a clear story for users who have older JavaInterop1-generated Java wrappers or handwritten Java copied from Java.Interop samples that still call `ManagedPeer.*`.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.