-
Notifications
You must be signed in to change notification settings - Fork 568
Description
Part of #10789
Overview
Implement the Java peer type scanner using System.Reflection.Metadata (SRM) — no Mono.Cecil. This is the foundation that all code generation builds on.
New project: src/Microsoft.Android.Sdk.TrimmableTypeMap/ — a dedicated assembly separate from Xamarin.Android.Build.Tasks for fast inner dev loop.
What this includes
Scanner (JavaPeerScanner)
- Open assemblies via
PEReader+MetadataReader - Find types with
[Register]attribute → extract JNI name andDoNotGenerateAcwflag - Detect activation constructors: XI style (
IntPtr, JniHandleOwnership) first, then JI style (ref JniObjectReference, JniObjectReferenceOptions) — walk up hierarchy if not on type itself - Collect marshal methods: methods with
[Register(name, sig, connector)]or[Export]attributes - Detect component attributes (
[Activity],[Service],[BroadcastReceiver],[ContentProvider],[Application],[Instrumentation]) for unconditional marking - Detect interface implementors and invoker types (including generic interface instantiations)
- Handle generic types: open generic definition gets the TypeMap entry
- Handle
[Application(BackupAgent=typeof(...))]and[Application(ManageSpaceActivity=typeof(...))]cross-references → force unconditional - Support
IJniNameProviderAttributefor custom JNI name resolution - Compute
CompatJniName(lowercased namespace) for acw-map.txt backward compatibility
Two-phase in-memory architecture (critical for performance)
Both PoCs suffered from O(n²) behavior scanning Mono.Android (~8000 types). The scanner uses:
Phase 1 — Index building (one pass per assembly):
TypesByFullName/TypesByJniNamedictionaries for O(1) lookupsRegisterInfoByType/AttributesByTypepre-indexed per typeIJniNameProviderAttributedetection and reclassification across assemblies- All state stays in memory — MSBuild
Inputs/Outputshandles target-level incrementality
Phase 2 — Type analysis (uses cached indices only):
ActivationCtorCache— hierarchy walk results shared across types with same baseextendsJavaPeerCache— cachesExtendsJavaPeerresults and doubles as cycle detection- Cross-assembly type resolution via
TryResolveType/ResolveRegisterJniNamehelpers
Performance target: <1s for Mono.Android (~8000 types).
CRC64 polynomial
The scanner uses System.IO.Hashing.Crc64 (ECMA polynomial) instead of the legacy Crc64Helper (Jones polynomial). This is intentional and safe. The CRC64 hash only needs to be self-consistent within a single compilation — the scanner computes the JNI name, the JCW generator uses it, the typemap records it, and acw-map.txt maps it. All consumers read from the same scan pass. See implementation update comment for details.
Data model
JavaPeerInfo {
JavaName, CompatJniName,
ManagedTypeName, ManagedTypeNamespace, ManagedTypeShortName,
AssemblyName, BaseJavaName, ImplementedInterfaceJavaNames,
IsInterface, IsAbstract, DoNotGenerateAcw,
IsUnconditional, IsGenericDefinition,
MarshalMethods[], JavaConstructors[],
ActivationCtor, InvokerTypeName?
}
MarshalMethodInfo {
JniName, JniSignature, Connector,
ManagedMethodName, DeclaringTypeName, DeclaringAssemblyName,
NativeCallbackName, Parameters[], JniReturnType,
IsConstructor, ThrownNames, SuperArgumentsString
}
Test projects
Unit tests (tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/):
- Hand-crafted test assembly (~20 types) for TDD inner loop
- 75 tests covering scanner logic, JNI parsing, edge cases
Integration tests (tests/Microsoft.Android.Sdk.TrimmableTypeMap.IntegrationTests/):
- Legacy comparison tests: Run both legacy Cecil-based scanner and new SRM scanner on same assemblies, compare results
- Real Mono.Android.dll (~8000 types) side-by-side comparison
UserTypesFixture.dll— user-type edge cases ([Activity], [Service], [Export], nested types, generic types, plain Java.Lang.Object subclasses)- 10 tests (type maps + marshal methods for both assemblies)
Type classification rules (spec §15.9)
| Type | Unconditional? | Gets JCW? | Gets RegisterNatives? |
|---|---|---|---|
User class with [Activity]/[Service]/etc |
✅ | ✅ | ✅ |
| Custom view from layout XML | ✅ | ✅ | ✅ |
| User class without component attr | Trimmable | ✅ | ✅ |
MCW binding (DoNotGenerateAcw=true) |
Trimmable | ❌ | ❌ |
| Interface | Trimmable | ❌ | ❌ |
| Invoker | Excluded | ❌ | ❌ |