Part of #10789
Depends on: Scanner sub-issue (PR1)
Overview
Implement the IL assembly generator and JCW Java source generator that transform JavaPeerInfo scan results into:
- Per-assembly typemap assemblies + root
_Microsoft.Android.TypeMaps.dll — using SRM Ecma335 APIs
- JCW Java source files — with
registerNatives in static {} blocks
TypeMap Assembly Generator (TypeMapAssemblyGenerator)
Uses SRM types: MetadataBuilder, BlobBuilder, InstructionEncoder, ControlFlowBuilder, MethodBodyStreamEncoder, PEHeaderBuilder.
Generated assembly contents
Assembly-level attributes:
[assembly: IgnoresAccessChecksTo("Mono.Android")] etc. for all referenced assemblies
[assembly: TypeMap<Java.Lang.Object>("jni/name", typeof(Proxy), typeof(TrimTarget))] — one per type
[assembly: TypeMapAssociation<AliasesUniverse>(typeof(Source), typeof(AliasHolder))] — for aliases
Per-type proxy classes — JavaPeerProxyAttribute subclasses:
- Self-application:
[Proxy] class Proxy : JavaPeerProxyAttribute
CreateInstance(IntPtr, JniHandleOwnership):
- MCW with own ctor:
new T(handle, transfer)
- User type without own ctor:
GetUninitializedObject(T) + direct call to base ctor (via IgnoresAccessChecksTo)
- Interface:
new TInvoker(handle, transfer)
- Generic:
throw new NotSupportedException()
GetContainerFactory(): return JavaPeerContainerFactory.Create<T>()
- For ACW types:
IAndroidCallableWrapper.RegisterNatives(JniType) + [UnmanagedCallersOnly] UCO methods (delegation or inlined)
Per-assembly output model (for incremental builds):
- One typemap assembly per input assembly with Java peer types
- Root assembly uses
[assembly: TypeMapAssemblyTarget<JLO>(assemblyName)] to reference per-assembly typemaps
- Alias detection and cross-ref forcing handled in root assembly
JCW Java Source Generator (JcwJavaSourceGenerator)
Generates .java files for ACW types (DoNotGenerateAcw=false):
package example;
public class MainActivity extends android.app.Activity
implements mono.android.IGCUserPeer
{
static { mono.android.Runtime.registerNatives(MainActivity.class); }
public MainActivity() { super(); if (getClass() == MainActivity.class) nctor_0(); }
private native void nctor_0();
@Override
public void onCreate(android.os.Bundle p0) { n_onCreate(p0); }
public native void n_onCreate(android.os.Bundle p0);
}
Key: generate Java class and IL proxy from the same ordered method list to ensure RegisterNatives connects the right native methods to the right UCO methods.
Tests
- Produces valid PE assembly loadable by
MetadataReader
- Generated assembly has correct
TypeMapAttribute entries (2-arg and 3-arg)
- Proxy types have correct self-application pattern
CreateInstance IL is valid for each ctor style
RegisterNatives method has correct JNI registrations
- UCO wrappers have
[UnmanagedCallersOnly] attribute
- Non-blittable params converted correctly (
byte for bool)
- Java source has
registerNatives in static {} block
- Correct
nctor_N declarations and @Override annotations
- Package names from
[Register], not CRC-hashed
Part of #10789
Depends on: Scanner sub-issue (PR1)
Overview
Implement the IL assembly generator and JCW Java source generator that transform
JavaPeerInfoscan results into:_Microsoft.Android.TypeMaps.dll— using SRM Ecma335 APIsregisterNativesinstatic {}blocksTypeMap Assembly Generator (
TypeMapAssemblyGenerator)Uses SRM types:
MetadataBuilder,BlobBuilder,InstructionEncoder,ControlFlowBuilder,MethodBodyStreamEncoder,PEHeaderBuilder.Generated assembly contents
Assembly-level attributes:
[assembly: IgnoresAccessChecksTo("Mono.Android")]etc. for all referenced assemblies[assembly: TypeMap<Java.Lang.Object>("jni/name", typeof(Proxy), typeof(TrimTarget))]— one per type[assembly: TypeMapAssociation<AliasesUniverse>(typeof(Source), typeof(AliasHolder))]— for aliasesPer-type proxy classes —
JavaPeerProxyAttributesubclasses:[Proxy] class Proxy : JavaPeerProxyAttributeCreateInstance(IntPtr, JniHandleOwnership):new T(handle, transfer)GetUninitializedObject(T)+ direct call to base ctor (viaIgnoresAccessChecksTo)new TInvoker(handle, transfer)throw new NotSupportedException()GetContainerFactory():return JavaPeerContainerFactory.Create<T>()IAndroidCallableWrapper.RegisterNatives(JniType)+[UnmanagedCallersOnly]UCO methods (delegation or inlined)Per-assembly output model (for incremental builds):
[assembly: TypeMapAssemblyTarget<JLO>(assemblyName)]to reference per-assembly typemapsJCW Java Source Generator (
JcwJavaSourceGenerator)Generates
.javafiles for ACW types (DoNotGenerateAcw=false):Key: generate Java class and IL proxy from the same ordered method list to ensure
RegisterNativesconnects the rightnativemethods to the right UCO methods.Tests
MetadataReaderTypeMapAttributeentries (2-arg and 3-arg)CreateInstanceIL is valid for each ctor styleRegisterNativesmethod has correct JNI registrations[UnmanagedCallersOnly]attributebyteforbool)registerNativesinstatic {}blocknctor_Ndeclarations and@Overrideannotations[Register], not CRC-hashed