Investigate eliminating generated ThresholdType and ThresholdClass overrides
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 35/100
Direzione di ricerca
Inizia dai file generati in obj/.../mcw/*.cs e segui Android.Runtime.XAPeerMembers.UsesVirtualDispatch(), GetPeerMembers() e gli accessor di threshold di Java.Lang.Object/Throwable. Confronta i casi di binding exact, subclass, invoker, cross-assembly e legacy nei runtime elencati. Il lavoro è completo quando è stato stabilito se gli override moderni possono essere omessi senza modificare il dispatch, preservando la semantica legacy e registrando i metadati richiesti e i confronti delle dimensioni.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Android framework version
net11.0-android (Preview) / .NET 12 investigation
Affected platform version
dotnet/android main; generated Mono.Android.dll and generated Java binding assemblies.
Description
The XAJavaInterop1 generator currently emits these overrides on nearly every generated bound class and invoker:
[DebuggerBrowsable (DebuggerBrowsableState.Never)]
[EditorBrowsable (EditorBrowsableState.Never)]
protected override IntPtr ThresholdClass
=> _members.JniPeerType.PeerReference.Handle;
[DebuggerBrowsable (DebuggerBrowsableState.Never)]
[EditorBrowsable (EditorBrowsableState.Never)]
protected override Type ThresholdType
=> _members.ManagedPeerType;
API 37 Mono.Android.dll contains approximately:
- 6,776 generated
ThresholdClassoverrides; - 7,447 generated
ThresholdTypeoverrides; - 28,446 associated
DebuggerBrowsable/EditorBrowsableattribute applications; - roughly 14,000 property rows, getter methods, method-semantics rows, bodies, and related metadata entries.
This appears to be an opportunity of more than 1 MB in the untrimmed framework assembly, but removal must not be attempted without understanding the legacy dispatch contract.
XAPeerMembers currently uses the properties to decide virtual versus nonvirtual managed-to-Java dispatch:
protected override bool UsesVirtualDispatch (IJavaPeerable value, Type? declaringType)
{
var peerType = GetThresholdType (value);
if (peerType != null)
return peerType == value.GetType ();
return base.UsesVirtualDispatch (value, declaringType);
}
It also uses ThresholdClass when selecting peer members for nonvirtual dispatch. This historically prevents incorrect recursion or dispatch when managed subclasses override Java virtual methods.
At first glance, modern generated types already expose equivalent information through:
value.JniPeerMembers.ManagedPeerType
value.JniPeerMembers.JniPeerType
The base JniPeerMembers.UsesVirtualDispatch() implementation already compares value.GetType() with value.JniPeerMembers.ManagedPeerType. We should investigate whether new-format binding assemblies can rely on this information and stop generating the per-type threshold overrides.
This must be considered separately from legacy binding compatibility. Old binding assemblies may:
- contain generated threshold overrides;
- contain hand-written threshold overrides;
- depend on
XAPeerMembershonoring those values; - derive from framework binding types across assembly boundaries; or
- use older generator/runtime dispatch assumptions.
A possible compatibility model is:
- Keep the protected virtual
ThresholdTypeandThresholdClassmembers onJava.Lang.Object/Throwableso old binaries remain loadable. - Stop emitting overrides in newly generated/version-marked bindings.
- Use
JniPeerMembers.ManagedPeerTypeandJniPeerTypefor modern bindings. - Detect and continue honoring threshold overrides from legacy binding assemblies, potentially keyed by an assembly/generator-format marker or a cached override-shape check.
The investigation should determine whether this split is correct or whether there are dispatch cases where the explicit threshold values carry information not available through JniPeerMembers.
Related size work: #12670.
Steps to Reproduce
- Generate
Mono.Android.dllfor API 37 with XAJavaInterop1. - Count generated
ThresholdTypeandThresholdClassoverrides inobj/.../mcw/*.csor the resulting assembly. - Trace
XAPeerMembers.UsesVirtualDispatch()andGetPeerMembers()through exact binding types, managed subclasses, Java subclasses, and invoker types. - Prototype omitting the generated overrides for a version-marked modern binding format while preserving the base virtual properties.
- Compare behavior against legacy binding assemblies built by older generators.
The prototype should cover at least:
- an exact generated binding type;
- a managed subclass overriding a Java virtual method;
- a Java-derived runtime type;
- abstract classes and interface invokers;
- cross-assembly inheritance;
- an old binding assembly containing generated threshold overrides;
- a legacy binding with a hand-written/custom threshold override;
- virtual and explicit nonvirtual calls;
- MonoVM, CoreCLR, and NativeAOT/trimmable-typemap configurations where applicable; and
- recursion prevention and correct Java method selection.
Acceptance criteria for an eventual implementation:
- New-format generated bindings omit
ThresholdType/ThresholdClassoverrides when they carry no additional information. - Managed-subclass and Java virtual-dispatch behavior remains unchanged.
- Legacy binding assemblies continue to load and preserve their threshold semantics.
- The protected base API remains binary compatible unless a separate breaking-change decision is made.
- Tests prove that no managed override recursion or wrong JNI nonvirtual class selection is introduced.
- Before/after
Mono.Android.dllmetadata, method, property, attribute, and final trimmed-app sizes are recorded.
Did you find any workaround?
No workaround is needed for correctness. The current generated properties preserve established behavior but impose repeated assembly-size and metadata costs.
Relevant log output
API 37 generated counts:
ThresholdClass overrides: 6,776
ThresholdType overrides: 7,447
Current runtime consumers:
- Android.Runtime.XAPeerMembers.UsesVirtualDispatch()
- Android.Runtime.XAPeerMembers.GetPeerMembers()
- Java.Lang.Object.GetThresholdType()/GetThresholdClass()
- Java.Lang.Throwable.GetThresholdType()/GetThresholdClass()
- Lingua principale
- C#
- Stelle
- 2.1k
- Fork
- 581
- Merge medio
- 2g 33m
- PR unite (30g)
- 204
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Nessuna guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di dotnet/android
-
Area: App+Library Build
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
I maintainer di solito rispondono entro 1 giorno
-
Area: Mono.Android
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
dotnet/android#9192 · 4 commenti · 1 reazione ·
I maintainer di solito rispondono entro 1 giorno
-
enhancement needs-triage
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
I maintainer di solito rispondono entro 1 giorno
-
[skill-runner] Weekly scanApertaautomated needs-triage skill-runner
Difficoltà 2/5 1-3 ore Idoneità per principianti 38/100
I maintainer di solito rispondono entro 1 giorno
-
[Java.Interop] Converge Android interop implementations and eliminate duplicate runtime pathsApertaneeds-triage
Difficoltà 5/5 Più di una settimana Idoneità per principianti 15/100
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di dotnet/android
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
MicrosoftLearning/PL-400_Microsoft-Power-Platform-Developer#231 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
joinrpg/joinrpg-net#5313 ·
I maintainer di solito rispondono entro 1 giorno
-
[12.x] FixIncorrectOwnerIdRelationships can delete legitimate library roots when UserView shares the same pathForse già presa Una pull request collegata a questa issue è aperta o già unita. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 79/100
I maintainer di solito rispondono entro 1 giorno