Skip to content

[TrimmableTypeMap] JcwJavaSourceGenerator must skip registerNatives for Application/Instrumentation types #10931

@simonrozsival

Description

@simonrozsival

Problem

The new JcwJavaSourceGenerator unconditionally emits mono.android.Runtime.registerNatives(Class) in the static initializer block for every JCW type. For Application and Instrumentation types, this will crash with UnsatisfiedLinkError because the native library (libmonodroid.so) is not loaded until the runtime ContentProvider runs — which happens after the Application class is loaded.

Android process startup order

1. Application class loaded (static {} runs)    ← registerNatives would run HERE
2. Application object instantiated
3. ContentProviders installed
4. MonoRuntimeProvider.attachInfo()
5.   → System.loadLibrary("monodroid")
6.   → Runtime.initInternal(...)                 ← Native JNI bridge ready HERE
7.   → ApplicationRegistration.registerApplications()
8. Application.onCreate()

How legacy solved it

The legacy CallableWrapperType has a CannotRegisterInStaticConstructor flag (IsApplication || IsInstrumentation) that:

  1. Skips Runtime.register(...) in the static block — the __md_methods string is built but registration is deferred
  2. Skips TypeManager.Activate(...) in constructors — normal activation is suppressed
  3. Defers registration to ApplicationRegistration.registerApplications() — generated by GenerateAdditionalProviderSources.cs, called at step 7 after the runtime is initialized

Relevant legacy code:

  • CallableWrapperType.cs:36: CannotRegisterInStaticConstructor => IsApplication || IsInstrumentation
  • CallableWrapperType.cs:272-273: skips registration in static block
  • CallableWrapperConstructor.cs:40: skips activation in ctor body
  • GenerateAdditionalProviderSources.cs:116-139: generates ApplicationRegistration.java with deferred registration calls

What needs to change in the new generator

  1. JavaPeerInfo (or the scanner) needs to expose whether a type is Application/Instrumentation
  2. JcwJavaSourceGenerator.WriteStaticInitializer() must skip registerNatives for these types
  3. JcwJavaSourceGenerator.WriteConstructors() must skip or adjust the nctor_N() call for these types
  4. The existing ApplicationRegistration infrastructure handles deferred registration — no changes needed there

Note on MonoPackageManager.setContext(this)

The legacy synthetic Application constructor called MonoPackageManager.setContext(this). This is now vestigial — both Mono and CLR runtime variants have // Ignore; vestigial in the method body. Context registration moved to ApplicationRegistration.Context = context during provider startup. No need to replicate this in the new generator.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions