Skip to content

[NativeAOT] Improve managed typemap #9910

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Mar 19, 2025

Conversation

simonrozsival
Copy link
Member

@simonrozsival simonrozsival commented Mar 12, 2025

This is a follow-up to #9856

#9846 showed that several tests are failing with the new managed type map. This PR addresses two of these issues:

  1. Use assembly qualified type name instead of just full name for the Managed -> Java mapping
  2. Generic types are handled correctly:
    • for managed -> java mapping, include all the different types which map to the same java class name (e.g., JavaList and JavaList<object> both map to java/util/ArrayList)
    • for java -> managed mapping, prefer non-generic base classes over generic subclasses (e.g., map java/util/ArrayList to JavaList instead of JavaList<>)

These changes now break roundtripping (JavaList<T> -> java/util/ArrayList -> JavaList). I implemented a new way of ensuring there isn't a runtime hash collision.

@simonrozsival simonrozsival marked this pull request as ready for review March 13, 2025 10:54
@simonrozsival simonrozsival requested a review from jonpryor as a code owner March 13, 2025 10:54
Copy link
Member

@jonathanpeppers jonathanpeppers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The APK tests that failed are networking related:

System.AggregateException : AggregateException_ctor_DefaultMessage (Ignoring network/server failure: ServiceUnavailable)
----> NUnit.Framework.IgnoreException : Ignoring network/server failure: ServiceUnavailable

They are also running on Mono, so shouldn't be using this NativeAOT code path anyway.

@jonpryor
Copy link
Contributor

jonpryor commented Mar 14, 2025

Draft commit message:

Context: https://github.com/dotnet/android/pull/9846
Context: efbec22767427f5704b6b20b3b36ff6c3c7067f2
Context: https://github.com/dotnet/android/issues/2266
Context: 684ede6a79da5b95eb9347c319683d8855f84d09
Context: https://github.com/xamarin/monodroid/commit/eb04c91c3f202d369c8a2930462ebff4f48b2e3e
Context: https://github.com/dotnet/java-interop/commit/397013edb915d7d3afc876993c502369de1ec015

`Java.Interop.JniRuntime.JniTypeManager` supports bi-directional
mapping between JNI type signatures and managed `Type`s:

  * `GetTypeSignature(Type)` returns the JNI type signature that
    corresponds to the `System.Type`.
  * `GetType(JniTypeSignature)` returns the `Type` that corresponds
    to a JNI type signature.

One can imagine 1:1 *identity relation* between Java and managed
types, in which `GetType(GetTypeSignature(t))==t`:

	static void Identity<T> ()
	{
	  JniRuntime.JniTypeManager tm  = Java.Interop.JniEnvironment.Runtime.TypeManager;
	  JniTypeSignature  sigFromT    = tm.GetTypeSignature (typeof (T));
	  Type?             typefromSig = tm.GetType (sigFromT);
	  if (typeof (T) != typefromSig)
	    throw new Exception ($"Type({typeof (T)}) != .GetType({sigFromT}){{{(typefromSig == null ? "<null>" : typefromSig.ToString ())}}}");
	  JniTypeSignature  sigIdentity = tm.GetTypeSignature (typefromSig!);
	  if (sigFromT != sigIdentity)
	    throw new Exception ($"{sigFromT}) != {sigIdentity}");
	}

This is *not* always true in .NET for Android.

There *is* a required 1:1 relation between Java and managed types for
"normal" user-written `Java.Lang.Object` and `Java.Lang.Throwable`
subclasses, such as:

	partial class MainActivity : Activity {
	}

There *may not* be a 1:1 relation between Java and managed types for:

  * Bindings/projections of Java types; that is, types which have
    `[Register(…, DoNotGenerateAcw=true)]` or
    `[JniTypeSignature(…, GenerateJavaPeer=false)]`.

  * *Arrays* of types.  The same `JniTypeSignature` is generated for
    for `T[]`, `JavaArray<T>`, and other `Java*Array` types.

For example, `Mono.Android.dll` contains *three* "binding aliases"
for `java.util.ArrayList`:

  * `Android.Runtime.JavaList`
  * `Android.Runtime.JavaList<T>`
  * `Java.Util.ArrayList`

Only `Identity<Android.Runtime.JavaList>()` passes on .NET 9.

There are *two* binding aliases for `java.lang.Object`:
`Java.Interop.JavaObject, Java.Interop` and
`Java.Lang.Object, Mono.Android`.  (Plus more in unit tests!)
Only `Identity<Java.Lang.Object>()` passes on .NET 9, and that's
because of special-casing (25d1f007, 7acf328e).

Which brings us to 684ede6a and dotnet/android#9846: there are two
additional issues with the improved NativeAOT-compatible typemap:

 1. It ignores assembly names when generating typemaps, and
 2. It doesn't properly deal with binding aliases.

## Assembly Identity is important!

It is not unusual for developers to copy and paste code
"from elsewhere" into their project.  It is likewise not unusual for
developers to *not* rename such copied code, meaning it is quite
possible for the "same" type to be present multiple times in an app:

	// Lib1.dll
	namespace Utilities {
	    class GenericHolder<T> : Java.Lang.Object {
	        public T Value {get; set;}
	    }
	}

	// Lib2.dll
	namespace Utilities {
	    class GenericHolder<T> : Java.Lang.Object {
	        public T Value {get; set;}
	    }
	}

From a C# and .NET perspective, this is fine:
`Utilities.GenericHolder<T>` has `internal` visibility; there is no
conflict here.

…except in pre-2014 Xamarin.Android, in which the package name of the
Java Callable Wrapper (JCW) name was based on the namespace of the
managed type.  *Both* of the above types would have the *same* JCW
name: `utilities.GenericHolder`.  This would promptly error out:

	error : Duplicate managed type found! Mappings between managed types and Java types must be unique.
	First Type: 'Android.Support.V4.App.FragmentManager/IOnBackStackChangedListenerImplementor, Xamarin.Android.Support.v4-r18, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null';
	Second Type: 'Android.Support.V4.App.FragmentManager/IOnBackStackChangedListenerImplementor, Mono.Android.Support.v4'

This scenario was improved in xamarin/monodroid@eb04c91c, which used
an *md5sum* of the namespace and assembly name, ensuring that the two
different `GenericHolder<T>` types would get different Java package
names, as the assembly name was in play.  (This was later changed to
use a CRC64 instead md5sum in dotnet/java-interop@397013ed.)

A problem in 684ede6a is that it would hash the managed type name for
a lookup, but the hash ignored the assembly name.  Consequently when
it countered two different `Java.InteropTests.GenericHolder<T>` types
in two separate assemblies, the assembly name was ignored, resulting
in a duplicate hash.  This would result in build failures:

	Fatal error in IL Linker
	Unhandled exception. System.InvalidOperationException: Duplicate hashes
	   at Microsoft.Android.Sdk.ILLink.TypeMappingStep.<>c__DisplayClass9_0.<EndProcess>g__GenerateHashes|10(UInt64[] hashes, String methodName)
	   at Microsoft.Android.Sdk.ILLink.TypeMappingStep.EndProcess()
	   at Mono.Linker.Steps.BaseStep.Process(LinkContext context)
	   at Mono.Linker.Pipeline.ProcessStep(LinkContext context, IStep step)
	   at Mono.Linker.Pipeline.Process(LinkContext context)
	   at Mono.Linker.Driver.Run(ILogger customLogger)
	   at Mono.Linker.Driver.Main(String[] args)

Fix this by hashing `Type.AssemblyQualifiedName` instead of
`Type.FullName`.

## Binding Aliases

dotnet/android#9846 had a unit test failure in
`JavaObjectExtensionsTests.JavaCast_BaseToGenericWrapper()`:

	System.ArgumentException : Could not determine Java type corresponding to ``Android.Runtime.JavaList`1[[System.Int32, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], Mono.Android``. Arg_ParamName_Name, targetType
	   at Java.Interop.JniRuntime.JniValueManager.CreatePeer(JniObjectReference&, JniObjectReferenceOptions, Type) + 0x248
	   at Java.Interop.JniRuntime.JniValueManager.GetPeer(JniObjectReference, Type) + 0x77
	   at Java.Lang.Object.GetObject(IntPtr, JniHandleOwnership, Type) + 0x31
	   at Java.Interop.JavaObjectExtensions._JavaCast[TResult](IJavaObject) + 0x66
	   at Java.InteropTests.JavaObjectExtensionsTests.JavaCast_BaseToGenericWrapper() + 0x62
	   at libMono.Android.NET-Tests!<BaseAddress>+0x1489b83
	   at System.Reflection.DynamicInvokeInfo.Invoke(Object, IntPtr, Object[], BinderBundle, Boolean) + 0xf3

This is due to "binding aliases": there was no type mapping between
`Android.Runtime.JavaList<T>` and `java/util/arrayList`, because the
typemaps were assuming a 1:1 mapping, which isn't the case here.

Update `TypeMappingStep` so that binding aliases are supported.

Given (from `TypeMappingStep.cs`):

	partial class TypeMappingStep {
	  IDictionary<string, List<TypeDefinition>> TypeMappings = new(StringComparer.Ordinal);
	}

Then at the end of trimming, `TypeMappingStep.TypeMappings` will
contain e.g.

	TypeMappingStep.TypeMappings = {
	  ["java/util/ArrayList"]   => new List<TypeDefinition> {
	    typeof (Android.Runtime.JavaList),
	    typeof (Android.Runtime.JavaList<>),
	    typeof (Java.Util.ArrayList),
	  },
	  ["java/lang/Object"]      => new List<TypeDefinition> {
	    typeof (Java.Lang.Object),
	    typeof (Java.Interop.JavaObject),
	  },
	  ["java/lang/Runnable"]    => new List<TypeDefinition> {
	    typeof (Java.Lang.IRunnable),
	    typeof (Java.Lang.IRunnableInvoker),
	  },
	  // …
	};

From `TypeMappingStep.TypeMappings` we produce two typemap "tables".

Java/JNI class name to managed type resembles:

	partial class TypeMapping {

	  static Type? GetTypeByJniNameHashIndex (int index) => index switch {
	    0  => Type.GetTypeFromHandle (typeof (Java.Lang.Byte).RuntimeTypeHandle),           // `java/lang/Byte`         hash=0x01cd624f1e38cc9f
	    32 => Type.GetTypeFromHandle (typeof (Android.Runtime.JavaList).RuntimeTypeHandle),	// `java/util/ArrayList`    hash=0x7b925bdca68a0101
	    56 => Type.GetTypeFromHandle (typeof (Java.Lang.Object).RuntimeTypeHandle),         // `java/lang/Object`       hash=0xbf6d427143271cb3 
	    77 => Type.GetTypeFromHandle (typeof (Java.Lang.IRunnable).RuntimeTypeHandle),      // `java/lang/Runnable`     hash=0xfd2b1a3de667eb51
	    _  => null,
	  };

	  static string? GetJniNameByJniNameHashIndex (int index) => index switch {
	    0  => "java/lang/Byte",         // `Java.Lang.Byte, Mono.Android`           hash=0x01cd624f1e38cc9f
	    32 => "java/util/ArrayList",    // `Android.Runtime.JavaList, Mono.Android` hash=0x7b925bdca68a0101
	    56 => "java/lang/Object",       // `Java.Lang.Object, Mono.Android`         hash=0xbf6d427143271cb3
	    77 => "java/lang/Runnable",     // `Java.Lang.IRunnable, Mono.Android`      hash=0xfd2b1a3de667eb51
	    _  => null,
	  };

	  private static ReadOnlySpan<ulong>  JniNameHashes => new ReadOnlySpan<ulong>(ref s_get_JniNameHashes_data, 78);

	  [StructLayout(LayoutKind.Explicit, Pack=1, Size=624)]
	  private struct HashesArray_624 {
	  }
	  private static HashesArray_624      s_get_JniNameHashes_data = new ulong[78]{ // RVA data; insert hand-waving here
	    0x1cd624f1e38cc9f,   //    0: java/lang/Byte
	    // …
	    0x7b925bdca68a0101,  //   32: java/util/ArrayList
	    // …
	    0xbf6d427143271cb3,  //   56: java/lang/Object
	    // …
	    0xfd2b1a3de667eb51,  //   77: java/lang/Runnable
	    // …
	  };
	}

Note that `TypeMapping.GetTypeByJniNameHashIndex()` and
`TypeMapping.GetJniNameByJniNameHashIndex()` provides values for all
indexes between 0 and the number of hashes within
`s_get_JniNameHashes_data`.  Not all entries are listed for
exposition purposes.

Managed type to JNI resembles:

	partial class TypeMapping {

	  static string? GetJniNameByTypeNameHashIndex (int index) => index switch {
	    0   => "java/lang/IndexOutOfBoundsException", // `Java.Lang.IndexOutOfBoundsException, Mono.Android`    hash=0x0242f4a673f183d1
	    2   => "java/util/ArrayList",                 // `Java.Util.ArrayList, Mono.Android`                    hash=0x07c2b62d20a668dd
	    4   => "java/util/ArrayList",                 // `Android.Runtime.JavaList`1, Mono.Android`             hash=0x132055d1acecc87d
	    30  => "java/lang/Runnable",                  // `Java.Lang.IRunnableInvoker, Mono.Android`             hash=0x386176afae6775ce
	    32  => "mono/java/lang/Runnable",             // `Java.Lang.Runnable, Mono.Android`                     hash=0x408566f4617e204f
	    36  => "java/util/ArrayList",                 // `Android.Runtime.JavaList, Mono.Android`               hash=0x48a63a89cfee545f
	    44  => "java/lang/Object",                    // `Java.Lang.Object, Mono.Android`                       hash=0x5b4a99c45538d0fb
	    51  => "java/lang/Object",                    // `Java.Interop.JavaObject, Java.Interop`                hash=0x88a12107f88ba9a7
	    53  => "java/lang/Byte",                      // `Java.Lang.Byte, Mono.Android`                         hash=0x8ab15b52718902fb
	    96  => "java/lang/Runnable",                  // `Java.Lang.IRunnable, Mono.Android`                    hash=0xef2efa58a51bb883 
	    _   => null,
	  };

	  static string? GetTypeNameByTypeNameHashIndex (int index) => index switch {
	    0   => "Java.Lang.IndexOutOfBoundsException, Mono.Android",   // `java/lang/IndexOutOfBoundsException`  hash=0x0242f4a673f183d1
	    2   => "Java.Util.ArrayList, Mono.Android",                   // `java/util/ArrayList`                  hash=0x07c2b62d20a668dd
	    4   => "Android.Runtime.JavaList`1, Mono.Android",            // `java/util/ArrayList`                  hash=0x132055d1acecc87d
	    30  => "Java.Lang.IRunnableInvoker, Mono.Android",            // `java/lang/Runnable`                   hash=0x386176afae6775ce
	    32  => "Java.Lang.Runnable, Mono.Android",                    // `mono/java/lang/Runnable`              hash=0x408566f4617e204f
	    36  => "Android.Runtime.JavaList, Mono.Android",              // `java/util/ArrayList`                  hash=0x48a63a89cfee545f
	    44  => "Java.Lang.Object, Mono.Android",                      // `java/lang/Object`                     hash=0x5b4a99c45538d0fb
	    51  => "Java.Interop.JavaObject, Java.Interop",               // `java/lang/Object`                     hash=0x88a12107f88ba9a7
	    53  => "Java.Lang.Byte, Mono.Android",                        // `java/lang/Byte`                       hash=0x8ab15b52718902fb
	    96  => "Java.Lang.IRunnable, Mono.Android",                   // `java/lang/Runnable`                   hash=0xef2efa58a51bb883
	    _   => null,
	  };

	  private static ReadOnlySpan<ulong>  TypeNameHashes => new ReadOnlySpan<ulong>(ref s_get_TypeNameHashes_data, 99);

	  [StructLayout(LayoutKind.Explicit, Pack=1, Size=792)]
	  private struct HashesArray_792 {
	  }
	  private static HashesArray_792      s_get_TypeNameHashes_data = new ulong[99] { // RVA data; insert hand-waving here
	    0x242f4a673f183d1,   //    0: Java.Lang.IndexOutOfBoundsException, Mono.Android
	    // …
	    0x7c2b62d20a668dd,   //    2: Java.Util.ArrayList, Mono.Android
	    // …
	    0x132055d1acecc87d,  //    4: Android.Runtime.JavaList`1, Mono.Android
	    // …
	    0x386176afae6775ce,  //   30: Java.Lang.IRunnableInvoker, Mono.Android
	    // …
	    0x408566f4617e204f,  //   32: Java.Lang.Runnable, Mono.Android
	    // …
	    0x48a63a89cfee545f,  //   36: Android.Runtime.JavaList, Mono.Android
	    // …
	    0x5b4a99c45538d0fb,  //   44: Java.Lang.Object, Mono.Android
	    // …
	    0x88a12107f88ba9a7,  //   51: Java.Interop.JavaObject, Java.Interop
	    // …
	    0x8ab15b52718902fb,  //   53: Java.Lang.Byte, Mono.Android
	    // …
	    0xef2efa58a51bb883,  //   96: Java.Lang.IRunnable, Mono.Android
	    // …
	  };
	}

Note that `TypeMapping.GetJniNameByTypeNameHashIndex()` and
`TypeMapping.GetTypeNameByTypeNameHashIndex()` provides values for all
indexes between 0 and the number of hashes within
`s_get_TypeNameHashes_data`.  Not all entries are listed for
exposition purposes.


var dotnetTypeNameHashes = orderedManagedToJavaMapping.Select (kvp => Hash (SelectTypeDefinition(kvp.Key, kvp.Value).FullName)).ToArray ();
GenerateHashes (dotnetTypeNameHashes, methodName: "get_TypeNameHashes");
var orderedManagedToJavaMapping = TypeMappings.SelectMany(kvp => kvp.Value.Select (type => new KeyValuePair<string, string>(kvp.Key, GetAssemblyQualifiedTypeName (type)))).OrderBy (kvp => Hash (kvp.Value)).ToArray ();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the TypeDefinition.GetAssemblyQualifiedName(string, IMetadataResolver) extension method overload, if possible:
https://github.com/dotnet/java-interop/blob/main/src/Java.Interop.Tools.Cecil/Java.Interop.Tools.Cecil/TypeDefinitionRocks.cs#L162-L173

We have found that providing and using the cache significantly speeds things up, and this code doesn't use a TypeDefinitionCache or IMetadataResolver cache.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coding style: I prefer "one expression per line", and would prefer:

var orderedManagedToJavaMapping = TypeMappings
    .SelectMany(kvp => kvp.Value.Select (type => new KeyValuePair<string, string>(kvp.Key, type.GetAssemblyQualifiedTypeName (cache))))
    .OrderBy (kvp => Hash (kvp.Value))
    .ToArray ();

.OrderBy (record => Hash (record.AssemblyQualifiedTypeName))
.ToArray ();

var assemblyQualifiedTypeNames = orderedManagedToJavaMapping.Select (record => record.AssemblyQualifiedTypeName).ToArray ();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@grendello are we till trying to avoid using Linq in the tasks and linker steps?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd hope so, it's still slower than plain, old, boring, hand-written code :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can remove the LINQ queries in a follow-up PR.

@simonrozsival
Copy link
Member Author

simonrozsival commented Mar 14, 2025

@jonpryor:

The generated IL includes several structs, (static) fields, properties, and methods:

  • RVA static fields containing the raw bytes of ulong[]
    • s_get_JavaClassNameHashes_data
    • s_get_TypeNameHashes_data
  • structs with explicit layout for the RVA static fields with an exact size ($"HashesArray_{bytes.Length}")
  • property getters which convert the RVA static fields into ReadOnlySpan<ulong>
    • ReadOnlySpan<ulong> TypeNameHashes { get; }
    • ReadOnlySpan<ulong> JavaClassNameHashes { get; }
  • lookup methods containing switch over index returning constants:
    • Type GetTypeByIndex(int index)
    • string GetJavaClassNameByTypeIndex(int index)
    • string GetJavaClassNameByIndex(int index)
    • string GetAssemblyQualifiedTypeNameByJavaClassNameIndex(int index)

Example of generated IL:

.class private auto ansi abstract sealed beforefieldinit Microsoft.Android.Runtime.TypeMapping
	extends [System.Private.CoreLib]System.Object
{
	// Nested Types
	.class nested private explicit ansi HashesArray_432
		extends [System.Private.CoreLib]System.ValueType
	{
		.pack 1
		.size 432
	} // end of class HashesArray_432

	.class nested private explicit ansi HashesArray_520
		extends [System.Private.CoreLib]System.ValueType
	{
		.pack 1
		.size 520
	} // end of class HashesArray_520

	// Fields
	.field private static initonly valuetype Microsoft.Android.Runtime.TypeMapping/HashesArray_432 s_get_JavaClassNameHashes_data at I_000050A0
	.data cil I_000050A0 = bytearray (
		9a 01 29 fb 99 a6 1d 0b c5 ed d9 21 2c 4c 7b 10
		...	
		38 16 36 2e 22 5f db e6 b3 e1 9b aa 70 ed 49 ed
		cc 69 d3 a1 96 29 2f ef 51 eb 67 e6 3d 1a 2b fd
	)

	.field private static initonly valuetype Microsoft.Android.Runtime.TypeMapping/HashesArray_520 s_get_TypeNameHashes_data at I_00005250
	.data cil I_00005250 = bytearray (
		61 6f 2b de bc 40 ae 06 74 67 7e 91 a6 74 86 0e
		...
		fe 76 b3 29 61 10 54 e5 4e d8 0d fd 3f 62 db e7
		83 b8 1b a5 58 fa 2e ef d2 37 aa 89 d5 ea 22 f0
		7c b2 61 76 1c b7 83 f9
	)

	.method private hidebysig specialname static 
		valuetype [System.Private.CoreLib]System.ReadOnlySpan`1<uint64> get_TypeNameHashes () cil managed 
	{
		// Method begins at RVA 0x4584
		// Header size: 12
		// Code size: 16 (0x10)
		.maxstack 2
		.locals init (
			[0] valuetype [System.Private.CoreLib]System.ReadOnlySpan`1<uint64>
		)

		IL_0000: ldsflda valuetype Microsoft.Android.Runtime.TypeMapping/HashesArray_520 Microsoft.Android.Runtime.TypeMapping::s_get_TypeNameHashes_data
		IL_0005: ldc.i4 65
		IL_000a: newobj instance void valuetype [System.Private.CoreLib]System.ReadOnlySpan`1<uint64>::.ctor(void*, int32)
		IL_000f: ret
	} // end of method TypeMapping::get_TypeNameHashes

	.method private hidebysig specialname static 
		valuetype [System.Private.CoreLib]System.ReadOnlySpan`1<uint64> get_JavaClassNameHashes () cil managed 
	{
		// Method begins at RVA 0x4b1c
		// Header size: 12
		// Code size: 16 (0x10)
		.maxstack 2
		.locals init (
			[0] valuetype [System.Private.CoreLib]System.ReadOnlySpan`1<uint64>
		)

		IL_0000: ldsflda valuetype Microsoft.Android.Runtime.TypeMapping/HashesArray_432 Microsoft.Android.Runtime.TypeMapping::s_get_JavaClassNameHashes_data
		IL_0005: ldc.i4 54
		IL_000a: newobj instance void valuetype [System.Private.CoreLib]System.ReadOnlySpan`1<uint64>::.ctor(void*, int32)
		IL_000f: ret
	} // end of method TypeMapping::get_JavaClassNameHashes

	.method private hidebysig static 
		class [System.Private.CoreLib]System.Type GetTypeByIndex (
			int32 index
		) cil managed 
	{
		.custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = (
			01 00 02 00 00
		)
		// Method begins at RVA 0x45a0
		// Header size: 12
		// Code size: 823 (0x337)
		.maxstack 1

		IL_0000: ldarg.0
		IL_0001: switch (IL_00e3, ..., IL_032a)

		IL_00de: br IL_0335

		IL_00e3: ldtoken [Mono.Android]Android.OS.BaseBundle
		IL_00e8: call class [System.Private.CoreLib]System.Type [System.Private.CoreLib]System.Type::GetTypeFromHandle(valuetype [System.Private.CoreLib]System.RuntimeTypeHandle)
		IL_00ed: ret

		...

		IL_032a: ldtoken [Mono.Android]Java.Lang.IRunnable
		IL_032f: call class [System.Private.CoreLib]System.Type [System.Private.CoreLib]System.Type::GetTypeFromHandle(valuetype [System.Private.CoreLib]System.RuntimeTypeHandle)
		IL_0334: ret

		IL_0335: ldnull
		IL_0336: ret
	} // end of method TypeMapping::GetTypeByIndex

	.method private hidebysig static 
		string GetJavaClassNameByTypeIndex (
			int32 index
		) cil managed 
	{
		.custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = (
			01 00 02 00 00
		)
		// Method begins at RVA 0x48e4
		// Header size: 12
		// Code size: 553 (0x229)
		.maxstack 1

		IL_0000: ldarg.0
		IL_0001: switch (IL_00e3, ..., IL_0221)

		IL_00de: br IL_0227

		IL_00e3: ldstr "android/os/BaseBundle"
		IL_00e8: ret

		... 

		IL_0221: ldstr "java/lang/Runnable"
		IL_0226: ret

		IL_0227: ldnull
		IL_0228: ret
	} // end of method TypeMapping::GetJavaClassNameByTypeIndex

	.method private hidebysig static 
		string GetJavaClassNameByIndex (
			int32 index
		) cil managed 
	{
		.custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = (
			01 00 02 00 00
		)
		// Method begins at RVA 0x4b38
		// Header size: 12
		// Code size: 663 (0x297)
		.maxstack 1

		IL_0000: ldarg.0
		IL_0001: switch (IL_010f, ..., IL_028f)

		IL_010a: br IL_0295

		IL_010f: ldstr "android/content/Context"
		IL_0114: ret

		...

		IL_028f: ldstr "java/lang/Throwable"
		IL_0294: ret

		IL_0295: ldnull
		IL_0296: ret
	} // end of method TypeMapping::GetJavaClassNameByIndex

	.method private hidebysig static 
		string GetAssemblyQualifiedTypeNameByJavaClassNameIndex (
			int32 index
		) cil managed 
	{
		.custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = (
			01 00 02 00 00
		)
		// Method begins at RVA 0x4ddc
		// Header size: 12
		// Code size: 663 (0x297)
		.maxstack 1

		IL_0000: ldarg.0
		IL_0001: switch (IL_010f, ..., IL_028f)

		IL_010a: br IL_0295

		IL_010f: ldstr "Android.Content.ContextInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"
		IL_0114: ret

		...

		IL_028f: ldstr "Java.Lang.Throwable, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"
		IL_0294: ret

		IL_0295: ldnull
		IL_0296: ret
	} // end of method TypeMapping::GetAssemblyQualifiedTypeNameByJavaClassNameIndex

} // end of class Microsoft.Android.Runtime.TypeMapping

if (fullName is null) {
className = null;

string? name = type.AssemblyQualifiedName;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we want or need to use the "full" .AssemblyQuaifiedName value here and in GetAssemblyQualifiedTypeNameByJavaClassNameIndex(), because all we really care about is assembly identity, not assembly versions; we have no mechanism to e.g. package both System.Drawing.dll v2.0 and v4.0. We don't have a GAC. Only one assembly version is ever packaged.

By using e.g. Android.Content.ContextInvoker, Mono.Android instead of Android.Content.ContextInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065, we save 67*2=134 bytes in the resulting IL, "simply" by not storing data that we don't care about.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right—we don't need the full AQN; the simple assembly name is enough for this use case. I'll revisit this.

I'm still unsure whether we need a hash collision check at all. The current native type map omits it, relying on xxHash64's extremely low collision probability.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if we do need it, I'm not sure why we need to be checking for collisions at runtime. A hash collision can be checked at build time.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can still have a runtime hash collision even when we check for build-time collisions. When someone passes an object to a marshal method and we try to look up its corresponding managed type, we ask the Java object for its class name and use that as an input to the type map.

This class name might be something we have not seen at build time (it could be some internal subclass of the base class we know at build time). Now when we hash this previously unknown class name, there's a positive chance it will collide with some hash of a different class name which is present in the type map.

The chance of this is very very close to zero and it likely wouldn't be possible to hit unless somebody constructs the input class name very carefully to achieve the collision. I don't know how that could be useful for an "attacker" though and if that's something we should or need to cover.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we want or need to use the "full" .AssemblyQuaifiedName value here and in GetAssemblyQualifiedTypeNameByJavaClassNameIndex(), because all we really care about is assembly identity, not assembly versions; we have no mechanism to e.g. package both System.Drawing.dll v2.0 and v4.0. We don't have a GAC. Only one assembly version is ever packaged.

We discussed this with @jonathanpeppers and the reason for using AQN was that it's much faster than calling assembly.GetName():

[Benchmark]
public string GetTypeAssemblyQualifiedName()
{
    var type = typeof(string);
    return type.AssemblyQualifiedName;
}

[Benchmark]
public string GetAssemblyName()
{
    var type = typeof(string);
    return $"{type.FullName}, {type.Assembly.GetName().Name}";
}
Method Mean Error StdDev
GetTypeAssemblyQualifiedName 35.79 ns 0.590 ns 1.123 ns
GetAssemblyName 407.84 ns 8.162 ns 13.860 ns

I updated the code to trim the unwanted suffix of the AssemblyQualifiedName to keep the perf of AssemblyQualifiedName but avoid those version mismatches.

@jonpryor
Copy link
Contributor

@simonrozsival: I've partially updated the draft commit message based on your your provided IL, but I'm still not sure I understand the "managed type to Java" mechanism.

Would it be possible to update your IL with the "known duplicates" -- assuming they survived trimming -- of Java.Interop.JavaObject + Java.Lang.Object, and/or Android.Runtime.JavaList + Android.Runtime.JavaList<T> + Java.Util.ArrayList?

Additionally, why is GetAssemblyQualifiedTypeNameByJavaClassNameIndex() mentioning Android.Content.ContextInvoker? Shouldn't it be using Android.Content.Context? Especially given SelectTypeDefinition(), which prefers abstract types?

From TryGetJavaClassName():

  1. ulong hash = Hash(type.AssemblyQualifiedName)

  2. int javaClassNameIndex = MemoryExtensions.BinarySearch (TypeNameHashes, hash);

    This is where I get confused; javaClassNameIndex is the index into TypeNameHashes of the hash value. But when we're dealing with "aliases", in which two different managed type names should refer to the same Java class name, how does this work? They should have different javaClassNameIndex values.

My expectation is that both TryGetJavaClassName(typeof(Android.Runtime.JavaList), …) and TryGetJavaClassName(typeof(Java.Util.ArrayList), …) would both "return" java/util/ArrayList, but I don't see how that is possible here.

Unrelatedly, the "ByIndex" methods are starting to confuse me. By what index? I think we need more nouns, especially as we only have two of these mappings running around and nomenclature is already annoying. Consider "GetJavaClassNameByTypeIndex"; which type? Managed or Java?

Perhaps:

  • GetTypeByIndex => GetTypeByTypeNameHashesIndex
  • GetJavaClassNameByTypeIndex => GetJavaClassNameByTypeNameHashesIndex
  • GetJavaClassNameByIndex => GetJavaClassNameByJavaClassNameHashesIndex

which would match the convention of "GetAssemblyQualifiedTypeNameByJavaClassNameIndex", which also re-emphasizes my concern around type aliases above:

@simonrozsival
Copy link
Member Author

simonrozsival commented Mar 17, 2025

This is where I get confused; javaClassNameIndex is the index into TypeNameHashes of the hash value. But when we're dealing with "aliases", in which two different managed type names should refer to the same Java class name, how does this work? They should have different javaClassNameIndex values.

@jonpryor if I understand your example, it is not clear to you how two different types can map to the same Java class name when they have different indexes into the TypeNameHashes table?

The answer is that there can be duplicate return values in the switch, as you correctly outlined it in the draft commit message:

static ulong[] s_get_TypeNameHashes_data = { 
    /* 0: */ 0xA, // xxhash64("Android.Runtime.JavaList"),
    /* 1: */ 0xB, // xxhash64("Java.Util.ArrayList"),
    ...
};

static string GetJavaClassNameByIndex(int typeNameHashesIndex)
    => typeNameHashesIndex switch {
        0 => "java/util/ArrayList",
        1 => "java/utilArrayList",
        ...
    };

static string GetAssemblyQualifiedTypeNameByIndex(int typeNameHashesIndex)
    => typeNameHashesIndex switch {
        0 => "Android.Runtime.JavaList, ...",
        1 => "Java.Util.ArrayList, ...",
        ...
    };

When the input is typeof(Android.Runtime.JavaList), this would be the order of operations:
1. The AQN "Android.Runtime.JavaList, ..." is hashed using xxhash64 -> 0xA
2. we find the index in TypeNameHashes using binary search -> 0
3. we confirm that the AQN of the input is actually correct and it is not just a hash collision by calling GetAssemblyQualifiedTypeNameByIndex(0)
4. we find the Java class name by calling GetJavaClassNameByIndex(0) -> "java/util/ArrayList"
5. we return the final string "java/util/ArrayList"

  1. int javaClassNameIndex = MemoryExtensions.BinarySearch (TypeNameHashes, hash);

This is where I get confused; javaClassNameIndex is the index into TypeNameHashes of the hash value. But when we're dealing with "aliases", in which two different managed type names should refer to the same Java class name, how does this work? They should have different javaClassNameIndex values.

The idea was that javaClassNameIndex is an index you would use to call the GetJavaClassNameByIndex method.
I agree that the *ByIndex suffixes are confusing and I like the names you suggested better. I will update the code based on your suggestion.

Additionally, why is GetAssemblyQualifiedTypeNameByJavaClassNameIndex() mentioning Android.Content.ContextInvoker? Shouldn't it be using Android.Content.Context? Especially given SelectTypeDefinition(), which prefers abstract types?

The GetAssemblyQualifiedTypeNameByJavaClassNameIndex method, which can return the "Android.Content.ContextInvoker" string, is used to confirm that there is no hash collision when typeof(Android.Content.ContentInvoker) is the input.

In other words, we won't return typeof(Android.Content.ContentInvoker) when we're looking for the managed type corresponding to "android/content/Context".


Related question: The more I keep working with this codebase, the more I'm starting to notice that I'm mixing the "Java class names" and "JNI names" without understanding the differences. Are JNI names class names where / is the separator and Java class names are separated with .? Should I also change the naming in the type map code?

@jonpryor
Copy link
Contributor

@simonrozsival asked:

Related question: The more I keep working with this codebase, the more I'm starting to notice that I'm mixing the "Java class names" and "JNI names" without understanding the differences. Are JNI names class names where / is the separator and Java class names are separated with .?

The "JNI name" is a string value which can be provided to JNIEnv::FindClass(string):

The name argument is a fully-qualified class name or an array type signature . For example, the fully-qualified class name for the java.lang.String class is:

"java/lang/String"

It's not "just" a "replace all .s with / from the Java class name". The problem is nested types, such as java.lang.Thread.UncaughtExceptionHandler. In Java, as with C#, nested types are separated from their declaring types with .. In JNI, as with IL, nested types are separated from their declaring types using a character other than .; JNI uses $, while IL uses / (and Reflection uses +).

Thus, the unambiguous name is always the JNI name, just as in .NET the unambiguous name is Type.AssemblyQualifiedName (+ not . for nested types):

  • Java: java.lang.Thread.UncaughtExceptionHandler
  • JNI: java/lang/Thread$UncaughtExceptionHandler

Should I also change the naming in the type map code?

This would be a good idea.

jonpryor and others added 4 commits March 17, 2025 17:30
[More input Stephane][0]!

[0]: https://www.youtube.com/watch?v=WnTKllDbu5o&t=72s

Why try to think through what all the numbers *are* and what the *mean*
when we can just have `TypeMappingStep` tell us?

Update `TypeMappingStep.EndProcess()` to print out human readable
contents of the generated members and RVA data blobs.

The one downside is *accessing* this additional output; to do so,
you need to use set `$(_ExtraTrimmerArgs)`=--verbose, e.g.

	android/dotnet-local.sh publish -p:PublishAot=true -v:diag -r android-arm64 -p:_ExtraTrimmerArgs=--verbose > b.txt

`b.txt` will then contain:

```
ILLink: JNI -> .NET mappings (TaskId:291)
ILLink: Generated field Microsoft.Android.Runtime.TypeMapping.s_get_JavaClassNameHashes_data contains 77 hashes: (TaskId:291)
ILLink: 	0x1cd624f1e38cc9f  //    0: java/lang/Byte (TaskId:291)
ILLink: 	0xb1da699fb29019a  //    1: android/os/BaseBundle (TaskId:291)
ILLink: 	0xc44130caa233945  //    2: mono/android/runtime/JavaObject (TaskId:291)
ILLink: 	0xd9335f0988cd796  //    3: java/util/HashMap (TaskId:291)
ILLink: 	0x107b4c2c21d9edc5 //    4: android/os/PersistableBundle (TaskId:291)
ILLink: 	0x194b32fbae047fc7 //    5: net/dot/jni/internal/JavaProxyObject (TaskId:291)
ILLink: 	0x1e69018626ef9ffb //    6: android/os/Handler (TaskId:291)
ILLink: 	0x225c20a45cb91cd7 //    7: java/lang/Error (TaskId:291)
ILLink: 	0x332031975eda7654 //    8: java/lang/Boolean (TaskId:291)
ILLink: 	0x35e989807a64bcd9 //    9: java/lang/IllegalStateException (TaskId:291)
ILLink: 	0x3695825e95d58a86 //   10: java/lang/ClassLoader (TaskId:291)
ILLink: 	0x39f1c81500ddb55b //   11: [F (TaskId:291)
ILLink: 	0x3c3c21010eb40849 //   12: crc6441ef2972864c2db2/MainActivity (TaskId:291)
ILLink: 	0x406e54c64b3bee74 //   13: android/runtime/JavaProxyThrowable (TaskId:291)
ILLink: 	0x4243a2addf0d7199 //   14: java/lang/ThreadGroup (TaskId:291)
ILLink: 	0x5181b129b1a25949 //   15: java/lang/Class (TaskId:291)
ILLink: 	0x5238ad63b58da994 //   16: java/lang/ClassCastException (TaskId:291)
ILLink: 	0x529da4201fa0d461 //   17: net/dot/jni/internal/JavaProxyThrowable (TaskId:291)
ILLink: 	0x551ac881eb4466c0 //   18: java/lang/Number (TaskId:291)
ILLink: 	0x560a92597b121e00 //   19: [C (TaskId:291)
ILLink: 	0x56365290d5a06704 //   20: java/lang/LinkageError (TaskId:291)
ILLink: 	0x5a6af884fe3c181e //   21: android/os/Bundle (TaskId:291)
ILLink: 	0x5bfd65ae1a6e6ffc //   22: android/app/Activity (TaskId:291)
ILLink: 	0x5f5a9fc3430795a4 //   23: android/content/ContextWrapper (TaskId:291)
ILLink: 	0x5f7e709faf8646e0 //   24: java/lang/Short (TaskId:291)
ILLink: 	0x61428f9f249ac534 //   25: [Z (TaskId:291)
ILLink: 	0x65f6b14b7e978927 //   26: java/io/IOException (TaskId:291)
ILLink: 	0x6e0fb15bd0f04d15 //   27: java/lang/StackTraceElement (TaskId:291)
ILLink: 	0x720cd712e1248c34 //   28: java/util/Iterator (TaskId:291)
ILLink: 	0x75591c18ddf5e52d //   29: mono/android/TypeManager (TaskId:291)
ILLink: 	0x76cbd2104dd555ed //   30: android/content/Context (TaskId:291)
ILLink: 	0x7b90c42bde036cae //   31: [I (TaskId:291)
ILLink: 	0x7b925bdca68a0101 //   32: java/util/ArrayList (TaskId:291)
ILLink: 	0x84f94178aab6cc34 //   33: java/lang/CharSequence (TaskId:291)
ILLink: 	0x888700b03d541d93 //   34: java/lang/RuntimeException (TaskId:291)
ILLink: 	0x88f7510c649f4a97 //   35: java/io/InputStream (TaskId:291)
ILLink: 	0x8a3ea3c274e8ce68 //   36: java/lang/Character (TaskId:291)
ILLink: 	0x90b4aeb45636cd6a //   37: mono/android/runtime/OutputStreamAdapter (TaskId:291)
ILLink: 	0x92188d393e2af2d2 //   38: java/lang/Throwable (TaskId:291)
ILLink: 	0x92b59c839bc46278 //   39: java/lang/Thread (TaskId:291)
ILLink: 	0x965bfaf1ff1da014 //   40: java/lang/ReflectiveOperationException (TaskId:291)
ILLink: 	0x98ba110c6c57da31 //   41: java/lang/Float (TaskId:291)
ILLink: 	0x99df91bab800c287 //   42: mono/android/runtime/InputStreamAdapter (TaskId:291)
ILLink: 	0x9a23c2d41060f81e //   43: java/io/File (TaskId:291)
ILLink: 	0x9a68fa465ca8abf9 //   44: java/io/FileDescriptor (TaskId:291)
ILLink: 	0x9e10a0b3efa170dc //   45: android/view/ContextThemeWrapper (TaskId:291)
ILLink: 	0x9fa1370a1b1093fa //   46: java/lang/NullPointerException (TaskId:291)
ILLink: 	0xa865adbdd81d9951 //   47: java/io/OutputStream (TaskId:291)
ILLink: 	0xabc3cd0f40f748aa //   48: java/lang/String (TaskId:291)
ILLink: 	0xac9902bb0e4c5217 //   49: java/lang/IllegalArgumentException (TaskId:291)
ILLink: 	0xacaf4fe23af1f72a //   50: [S (TaskId:291)
ILLink: 	0xada6872f699d2ae8 //   51: [J (TaskId:291)
ILLink: 	0xb02badeb1c97535c //   52: java/lang/Integer (TaskId:291)
ILLink: 	0xb18d71343ca8e96f //   53: java/lang/Exception (TaskId:291)
ILLink: 	0xb6c4749da9477c3a //   54: [B (TaskId:291)
ILLink: 	0xbb84ccbe48f6c18b //   55: android/os/Looper (TaskId:291)
ILLink: 	0xbf6d427143271cb3 //   56: java/lang/Object (TaskId:291)
ILLink: 	0xc00f4c2f11efdcff //   57: java/lang/ClassNotFoundException (TaskId:291)
ILLink: 	0xc2a8e50a5f08afc6 //   58: mono/java/lang/RunnableImplementor (TaskId:291)
ILLink: 	0xca35caf567cfa745 //   59: java/util/Collection (TaskId:291)
ILLink: 	0xcc306823503920e9 //   60: android/app/Application (TaskId:291)
ILLink: 	0xd1b288a9c7bb8f53 //   61: java/lang/Double (TaskId:291)
ILLink: 	0xd2fc750314fd2213 //   62: [D (TaskId:291)
ILLink: 	0xdd812f1d4afa427b //   63: java/lang/UnsupportedOperationException (TaskId:291)
ILLink: 	0xdfabd9351f4351a6 //   64: [Ljava/lang/Object; (TaskId:291)
ILLink: 	0xe024b538ad65ea66 //   65: java/util/function/Consumer (TaskId:291)
ILLink: 	0xe0446bf91fb0c2dd //   66: java/lang/NoClassDefFoundError (TaskId:291)
ILLink: 	0xe1b3c5871398eb28 //   67: java/nio/channels/FileChannel (TaskId:291)
ILLink: 	0xe5abbaa9de37d34b //   68: net/dot/jni/ManagedPeer (TaskId:291)
ILLink: 	0xeb82145dcac4c559 //   69: java/lang/Long (TaskId:291)
ILLink: 	0xed49ed70aa9be1b3 //   70: java/nio/channels/spi/AbstractInterruptibleChannel (TaskId:291)
ILLink: 	0xef2f2996a1d369cc //   71: java/io/FileInputStream (TaskId:291)
ILLink: 	0xf11f22a6441fcfbc //   72: java/lang/IndexOutOfBoundsException (TaskId:291)
ILLink: 	0xf6992bc6c5609046 //   73: java/util/AbstractList (TaskId:291)
ILLink: 	0xf9ad79a231c20217 //   74: java/util/AbstractCollection (TaskId:291)
ILLink: 	0xfbe9bfa5cc50fed6 //   75: java/util/HashSet (TaskId:291)
ILLink: 	0xfd2b1a3de667eb51 //   76: java/lang/Runnable (TaskId:291)
ILLink: Generated method Microsoft.Android.Runtime.TypeMapping.GetTypeByIndex contains 77 mappings: (TaskId:291)
ILLink: 	index    0 => "Java.Lang.Byte, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                                    , // `java/lang/Byte` hash=0x01cd624f1e38cc9f (TaskId:291)
ILLink: 	index    1 => "Android.OS.BaseBundle, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                             , // `android/os/BaseBundle` hash=0x0b1da699fb29019a (TaskId:291)
ILLink: 	index    2 => "Android.Runtime.JavaObject, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                        , // `mono/android/runtime/JavaObject` hash=0x0c44130caa233945 (TaskId:291)
ILLink: 	index    3 => "Android.Runtime.JavaDictionary, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                    , // `java/util/HashMap` hash=0x0d9335f0988cd796 (TaskId:291)
ILLink: 	index    4 => "Android.OS.PersistableBundle, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                      , // `android/os/PersistableBundle` hash=0x107b4c2c21d9edc5 (TaskId:291)
ILLink: 	index    5 => "Java.Interop.JavaProxyObject, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                     , // `net/dot/jni/internal/JavaProxyObject` hash=0x194b32fbae047fc7 (TaskId:291)
ILLink: 	index    6 => "Android.OS.Handler, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                                , // `android/os/Handler` hash=0x1e69018626ef9ffb (TaskId:291)
ILLink: 	index    7 => "Java.Lang.Error, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                                   , // `java/lang/Error` hash=0x225c20a45cb91cd7 (TaskId:291)
ILLink: 	index    8 => "Java.Lang.Boolean, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                                 , // `java/lang/Boolean` hash=0x332031975eda7654 (TaskId:291)
ILLink: 	index    9 => "Java.Lang.IllegalStateException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                   , // `java/lang/IllegalStateException` hash=0x35e989807a64bcd9 (TaskId:291)
ILLink: 	index   10 => "Java.Lang.ClassLoader, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                             , // `java/lang/ClassLoader` hash=0x3695825e95d58a86 (TaskId:291)
ILLink: 	index   11 => "Java.Interop.JavaSingleArray, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                     , // `[F` hash=0x39f1c81500ddb55b (TaskId:291)
ILLink: 	index   12 => "android_identity.MainActivity, android-identity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"                             , // `crc6441ef2972864c2db2/MainActivity` hash=0x3c3c21010eb40849 (TaskId:291)
ILLink: 	index   13 => "Android.Runtime.JavaProxyThrowable, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                , // `android/runtime/JavaProxyThrowable` hash=0x406e54c64b3bee74 (TaskId:291)
ILLink: 	index   14 => "Java.Lang.ThreadGroup, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                             , // `java/lang/ThreadGroup` hash=0x4243a2addf0d7199 (TaskId:291)
ILLink: 	index   15 => "Java.Lang.Class, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                                   , // `java/lang/Class` hash=0x5181b129b1a25949 (TaskId:291)
ILLink: 	index   16 => "Java.Lang.ClassCastException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                      , // `java/lang/ClassCastException` hash=0x5238ad63b58da994 (TaskId:291)
ILLink: 	index   17 => "Java.Interop.JavaProxyThrowable, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                  , // `net/dot/jni/internal/JavaProxyThrowable` hash=0x529da4201fa0d461 (TaskId:291)
ILLink: 	index   18 => "Java.Lang.Number, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                                  , // `java/lang/Number` hash=0x551ac881eb4466c0 (TaskId:291)
ILLink: 	index   19 => "Java.Interop.JavaCharArray, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                       , // `[C` hash=0x560a92597b121e00 (TaskId:291)
ILLink: 	index   20 => "Java.Lang.LinkageError, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                            , // `java/lang/LinkageError` hash=0x56365290d5a06704 (TaskId:291)
ILLink: 	index   21 => "Android.OS.Bundle, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                                 , // `android/os/Bundle` hash=0x5a6af884fe3c181e (TaskId:291)
ILLink: 	index   22 => "Android.App.Activity, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                              , // `android/app/Activity` hash=0x5bfd65ae1a6e6ffc (TaskId:291)
ILLink: 	index   23 => "Android.Content.ContextWrapper, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                    , // `android/content/ContextWrapper` hash=0x5f5a9fc3430795a4 (TaskId:291)
ILLink: 	index   24 => "Java.Lang.Short, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                                   , // `java/lang/Short` hash=0x5f7e709faf8646e0 (TaskId:291)
ILLink: 	index   25 => "Java.Interop.JavaBooleanArray, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                    , // `[Z` hash=0x61428f9f249ac534 (TaskId:291)
ILLink: 	index   26 => "Java.IO.IOException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                               , // `java/io/IOException` hash=0x65f6b14b7e978927 (TaskId:291)
ILLink: 	index   27 => "Java.Lang.StackTraceElement, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                       , // `java/lang/StackTraceElement` hash=0x6e0fb15bd0f04d15 (TaskId:291)
ILLink: 	index   28 => "Java.Util.IIterator, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                               , // `java/util/Iterator` hash=0x720cd712e1248c34 (TaskId:291)
ILLink: 	index   29 => "Java.Interop.TypeManager+JavaTypeManager, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"          , // `mono/android/TypeManager` hash=0x75591c18ddf5e52d (TaskId:291)
ILLink: 	index   30 => "Android.Content.Context, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                           , // `android/content/Context` hash=0x76cbd2104dd555ed (TaskId:291)
ILLink: 	index   31 => "Java.Interop.JavaInt32Array, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                      , // `[I` hash=0x7b90c42bde036cae (TaskId:291)
ILLink: 	index   32 => "Android.Runtime.JavaList, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                          , // `java/util/ArrayList` hash=0x7b925bdca68a0101 (TaskId:291)
ILLink: 	index   33 => "Java.Lang.ICharSequenceInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                    , // `java/lang/CharSequence` hash=0x84f94178aab6cc34 (TaskId:291)
ILLink: 	index   34 => "Java.Lang.RuntimeException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                        , // `java/lang/RuntimeException` hash=0x888700b03d541d93 (TaskId:291)
ILLink: 	index   35 => "Java.IO.InputStream, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                               , // `java/io/InputStream` hash=0x88f7510c649f4a97 (TaskId:291)
ILLink: 	index   36 => "Java.Lang.Character, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                               , // `java/lang/Character` hash=0x8a3ea3c274e8ce68 (TaskId:291)
ILLink: 	index   37 => "Android.Runtime.OutputStreamAdapter, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"               , // `mono/android/runtime/OutputStreamAdapter` hash=0x90b4aeb45636cd6a (TaskId:291)
ILLink: 	index   38 => "Java.Lang.Throwable, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                               , // `java/lang/Throwable` hash=0x92188d393e2af2d2 (TaskId:291)
ILLink: 	index   39 => "Java.Lang.Thread, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                                  , // `java/lang/Thread` hash=0x92b59c839bc46278 (TaskId:291)
ILLink: 	index   40 => "Java.Lang.ReflectiveOperationException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"            , // `java/lang/ReflectiveOperationException` hash=0x965bfaf1ff1da014 (TaskId:291)
ILLink: 	index   41 => "Java.Lang.Float, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                                   , // `java/lang/Float` hash=0x98ba110c6c57da31 (TaskId:291)
ILLink: 	index   42 => "Android.Runtime.InputStreamAdapter, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                , // `mono/android/runtime/InputStreamAdapter` hash=0x99df91bab800c287 (TaskId:291)
ILLink: 	index   43 => "Java.IO.File, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                                      , // `java/io/File` hash=0x9a23c2d41060f81e (TaskId:291)
ILLink: 	index   44 => "Java.IO.FileDescriptor, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                            , // `java/io/FileDescriptor` hash=0x9a68fa465ca8abf9 (TaskId:291)
ILLink: 	index   45 => "Android.Views.ContextThemeWrapper, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                 , // `android/view/ContextThemeWrapper` hash=0x9e10a0b3efa170dc (TaskId:291)
ILLink: 	index   46 => "Java.Lang.NullPointerException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                    , // `java/lang/NullPointerException` hash=0x9fa1370a1b1093fa (TaskId:291)
ILLink: 	index   47 => "Java.IO.OutputStream, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                              , // `java/io/OutputStream` hash=0xa865adbdd81d9951 (TaskId:291)
ILLink: 	index   48 => "Java.Lang.String, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                                  , // `java/lang/String` hash=0xabc3cd0f40f748aa (TaskId:291)
ILLink: 	index   49 => "Java.Lang.IllegalArgumentException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                , // `java/lang/IllegalArgumentException` hash=0xac9902bb0e4c5217 (TaskId:291)
ILLink: 	index   50 => "Java.Interop.JavaInt16Array, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                      , // `[S` hash=0xacaf4fe23af1f72a (TaskId:291)
ILLink: 	index   51 => "Java.Interop.JavaInt64Array, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                      , // `[J` hash=0xada6872f699d2ae8 (TaskId:291)
ILLink: 	index   52 => "Java.Lang.Integer, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                                 , // `java/lang/Integer` hash=0xb02badeb1c97535c (TaskId:291)
ILLink: 	index   53 => "Java.Lang.Exception, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                               , // `java/lang/Exception` hash=0xb18d71343ca8e96f (TaskId:291)
ILLink: 	index   54 => "Java.Interop.JavaSByteArray, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                      , // `[B` hash=0xb6c4749da9477c3a (TaskId:291)
ILLink: 	index   55 => "Android.OS.Looper, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                                 , // `android/os/Looper` hash=0xbb84ccbe48f6c18b (TaskId:291)
ILLink: 	index   56 => "Java.Lang.Object, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                                  , // `java/lang/Object` hash=0xbf6d427143271cb3 (TaskId:291)
ILLink: 	index   57 => "Java.Lang.ClassNotFoundException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                  , // `java/lang/ClassNotFoundException` hash=0xc00f4c2f11efdcff (TaskId:291)
ILLink: 	index   58 => "Java.Lang.Thread+RunnableImplementor, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"              , // `mono/java/lang/RunnableImplementor` hash=0xc2a8e50a5f08afc6 (TaskId:291)
ILLink: 	index   59 => "Android.Runtime.JavaCollection, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                    , // `java/util/Collection` hash=0xca35caf567cfa745 (TaskId:291)
ILLink: 	index   60 => "Android.App.Application, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                           , // `android/app/Application` hash=0xcc306823503920e9 (TaskId:291)
ILLink: 	index   61 => "Java.Lang.Double, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                                  , // `java/lang/Double` hash=0xd1b288a9c7bb8f53 (TaskId:291)
ILLink: 	index   62 => "Java.Interop.JavaDoubleArray, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                     , // `[D` hash=0xd2fc750314fd2213 (TaskId:291)
ILLink: 	index   63 => "Java.Lang.UnsupportedOperationException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"           , // `java/lang/UnsupportedOperationException` hash=0xdd812f1d4afa427b (TaskId:291)
ILLink: 	index   64 => "Java.Interop.JavaArray`1, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                         , // `[Ljava/lang/Object;` hash=0xdfabd9351f4351a6 (TaskId:291)
ILLink: 	index   65 => "Java.Util.Functions.IConsumer, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                     , // `java/util/function/Consumer` hash=0xe024b538ad65ea66 (TaskId:291)
ILLink: 	index   66 => "Java.Lang.NoClassDefFoundError, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                    , // `java/lang/NoClassDefFoundError` hash=0xe0446bf91fb0c2dd (TaskId:291)
ILLink: 	index   67 => "Java.Nio.Channels.FileChannel, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                     , // `java/nio/channels/FileChannel` hash=0xe1b3c5871398eb28 (TaskId:291)
ILLink: 	index   68 => "Java.Interop.ManagedPeer, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                         , // `net/dot/jni/ManagedPeer` hash=0xe5abbaa9de37d34b (TaskId:291)
ILLink: 	index   69 => "Java.Lang.Long, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                                    , // `java/lang/Long` hash=0xeb82145dcac4c559 (TaskId:291)
ILLink: 	index   70 => "Java.Nio.Channels.Spi.AbstractInterruptibleChannel, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065", // `java/nio/channels/spi/AbstractInterruptibleChannel` hash=0xed49ed70aa9be1b3 (TaskId:291)
ILLink: 	index   71 => "Java.IO.FileInputStream, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                           , // `java/io/FileInputStream` hash=0xef2f2996a1d369cc (TaskId:291)
ILLink: 	index   72 => "Java.Lang.IndexOutOfBoundsException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"               , // `java/lang/IndexOutOfBoundsException` hash=0xf11f22a6441fcfbc (TaskId:291)
ILLink: 	index   73 => "Java.Util.AbstractList, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                            , // `java/util/AbstractList` hash=0xf6992bc6c5609046 (TaskId:291)
ILLink: 	index   74 => "Java.Util.AbstractCollection, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                      , // `java/util/AbstractCollection` hash=0xf9ad79a231c20217 (TaskId:291)
ILLink: 	index   75 => "Android.Runtime.JavaSet, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                           , // `java/util/HashSet` hash=0xfbe9bfa5cc50fed6 (TaskId:291)
ILLink: 	index   76 => "Java.Lang.IRunnable, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065"                               , // `java/lang/Runnable` hash=0xfd2b1a3de667eb51 (TaskId:291)
ILLink: Generated method Microsoft.Android.Runtime.TypeMapping.GetJavaClassNameByTypeIndex contains 77 mappings: (TaskId:291)
ILLink: 	index    0 => "java/lang/Byte"                                    , // `Java.Lang.Byte, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x01cd624f1e38cc9f (TaskId:291)
ILLink: 	index    1 => "android/os/BaseBundle"                             , // `Android.OS.BaseBundle, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x0b1da699fb29019a (TaskId:291)
ILLink: 	index    2 => "mono/android/runtime/JavaObject"                   , // `Android.Runtime.JavaObject, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x0c44130caa233945 (TaskId:291)
ILLink: 	index    3 => "java/util/HashMap"                                 , // `Android.Runtime.JavaDictionary, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x0d9335f0988cd796 (TaskId:291)
ILLink: 	index    4 => "android/os/PersistableBundle"                      , // `Android.OS.PersistableBundle, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x107b4c2c21d9edc5 (TaskId:291)
ILLink: 	index    5 => "net/dot/jni/internal/JavaProxyObject"              , // `Java.Interop.JavaProxyObject, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x194b32fbae047fc7 (TaskId:291)
ILLink: 	index    6 => "android/os/Handler"                                , // `Android.OS.Handler, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x1e69018626ef9ffb (TaskId:291)
ILLink: 	index    7 => "java/lang/Error"                                   , // `Java.Lang.Error, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x225c20a45cb91cd7 (TaskId:291)
ILLink: 	index    8 => "java/lang/Boolean"                                 , // `Java.Lang.Boolean, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x332031975eda7654 (TaskId:291)
ILLink: 	index    9 => "java/lang/IllegalStateException"                   , // `Java.Lang.IllegalStateException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x35e989807a64bcd9 (TaskId:291)
ILLink: 	index   10 => "java/lang/ClassLoader"                             , // `Java.Lang.ClassLoader, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x3695825e95d58a86 (TaskId:291)
ILLink: 	index   11 => "[F"                                                , // `Java.Interop.JavaSingleArray, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x39f1c81500ddb55b (TaskId:291)
ILLink: 	index   12 => "crc6441ef2972864c2db2/MainActivity"                , // `android_identity.MainActivity, android-identity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null` hash=0x3c3c21010eb40849 (TaskId:291)
ILLink: 	index   13 => "android/runtime/JavaProxyThrowable"                , // `Android.Runtime.JavaProxyThrowable, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x406e54c64b3bee74 (TaskId:291)
ILLink: 	index   14 => "java/lang/ThreadGroup"                             , // `Java.Lang.ThreadGroup, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x4243a2addf0d7199 (TaskId:291)
ILLink: 	index   15 => "java/lang/Class"                                   , // `Java.Lang.Class, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x5181b129b1a25949 (TaskId:291)
ILLink: 	index   16 => "java/lang/ClassCastException"                      , // `Java.Lang.ClassCastException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x5238ad63b58da994 (TaskId:291)
ILLink: 	index   17 => "net/dot/jni/internal/JavaProxyThrowable"           , // `Java.Interop.JavaProxyThrowable, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x529da4201fa0d461 (TaskId:291)
ILLink: 	index   18 => "java/lang/Number"                                  , // `Java.Lang.Number, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x551ac881eb4466c0 (TaskId:291)
ILLink: 	index   19 => "[C"                                                , // `Java.Interop.JavaCharArray, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x560a92597b121e00 (TaskId:291)
ILLink: 	index   20 => "java/lang/LinkageError"                            , // `Java.Lang.LinkageError, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x56365290d5a06704 (TaskId:291)
ILLink: 	index   21 => "android/os/Bundle"                                 , // `Android.OS.Bundle, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x5a6af884fe3c181e (TaskId:291)
ILLink: 	index   22 => "android/app/Activity"                              , // `Android.App.Activity, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x5bfd65ae1a6e6ffc (TaskId:291)
ILLink: 	index   23 => "android/content/ContextWrapper"                    , // `Android.Content.ContextWrapper, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x5f5a9fc3430795a4 (TaskId:291)
ILLink: 	index   24 => "java/lang/Short"                                   , // `Java.Lang.Short, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x5f7e709faf8646e0 (TaskId:291)
ILLink: 	index   25 => "[Z"                                                , // `Java.Interop.JavaBooleanArray, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x61428f9f249ac534 (TaskId:291)
ILLink: 	index   26 => "java/io/IOException"                               , // `Java.IO.IOException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x65f6b14b7e978927 (TaskId:291)
ILLink: 	index   27 => "java/lang/StackTraceElement"                       , // `Java.Lang.StackTraceElement, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x6e0fb15bd0f04d15 (TaskId:291)
ILLink: 	index   28 => "java/util/Iterator"                                , // `Java.Util.IIterator, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x720cd712e1248c34 (TaskId:291)
ILLink: 	index   29 => "mono/android/TypeManager"                          , // `Java.Interop.TypeManager+JavaTypeManager, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x75591c18ddf5e52d (TaskId:291)
ILLink: 	index   30 => "android/content/Context"                           , // `Android.Content.Context, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x76cbd2104dd555ed (TaskId:291)
ILLink: 	index   31 => "[I"                                                , // `Java.Interop.JavaInt32Array, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x7b90c42bde036cae (TaskId:291)
ILLink: 	index   32 => "java/util/ArrayList"                               , // `Android.Runtime.JavaList, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x7b925bdca68a0101 (TaskId:291)
ILLink: 	index   33 => "java/lang/CharSequence"                            , // `Java.Lang.ICharSequenceInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x84f94178aab6cc34 (TaskId:291)
ILLink: 	index   34 => "java/lang/RuntimeException"                        , // `Java.Lang.RuntimeException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x888700b03d541d93 (TaskId:291)
ILLink: 	index   35 => "java/io/InputStream"                               , // `Java.IO.InputStream, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x88f7510c649f4a97 (TaskId:291)
ILLink: 	index   36 => "java/lang/Character"                               , // `Java.Lang.Character, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x8a3ea3c274e8ce68 (TaskId:291)
ILLink: 	index   37 => "mono/android/runtime/OutputStreamAdapter"          , // `Android.Runtime.OutputStreamAdapter, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x90b4aeb45636cd6a (TaskId:291)
ILLink: 	index   38 => "java/lang/Throwable"                               , // `Java.Lang.Throwable, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x92188d393e2af2d2 (TaskId:291)
ILLink: 	index   39 => "java/lang/Thread"                                  , // `Java.Lang.Thread, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x92b59c839bc46278 (TaskId:291)
ILLink: 	index   40 => "java/lang/ReflectiveOperationException"            , // `Java.Lang.ReflectiveOperationException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x965bfaf1ff1da014 (TaskId:291)
ILLink: 	index   41 => "java/lang/Float"                                   , // `Java.Lang.Float, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x98ba110c6c57da31 (TaskId:291)
ILLink: 	index   42 => "mono/android/runtime/InputStreamAdapter"           , // `Android.Runtime.InputStreamAdapter, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x99df91bab800c287 (TaskId:291)
ILLink: 	index   43 => "java/io/File"                                      , // `Java.IO.File, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x9a23c2d41060f81e (TaskId:291)
ILLink: 	index   44 => "java/io/FileDescriptor"                            , // `Java.IO.FileDescriptor, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x9a68fa465ca8abf9 (TaskId:291)
ILLink: 	index   45 => "android/view/ContextThemeWrapper"                  , // `Android.Views.ContextThemeWrapper, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x9e10a0b3efa170dc (TaskId:291)
ILLink: 	index   46 => "java/lang/NullPointerException"                    , // `Java.Lang.NullPointerException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x9fa1370a1b1093fa (TaskId:291)
ILLink: 	index   47 => "java/io/OutputStream"                              , // `Java.IO.OutputStream, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xa865adbdd81d9951 (TaskId:291)
ILLink: 	index   48 => "java/lang/String"                                  , // `Java.Lang.String, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xabc3cd0f40f748aa (TaskId:291)
ILLink: 	index   49 => "java/lang/IllegalArgumentException"                , // `Java.Lang.IllegalArgumentException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xac9902bb0e4c5217 (TaskId:291)
ILLink: 	index   50 => "[S"                                                , // `Java.Interop.JavaInt16Array, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xacaf4fe23af1f72a (TaskId:291)
ILLink: 	index   51 => "[J"                                                , // `Java.Interop.JavaInt64Array, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xada6872f699d2ae8 (TaskId:291)
ILLink: 	index   52 => "java/lang/Integer"                                 , // `Java.Lang.Integer, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xb02badeb1c97535c (TaskId:291)
ILLink: 	index   53 => "java/lang/Exception"                               , // `Java.Lang.Exception, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xb18d71343ca8e96f (TaskId:291)
ILLink: 	index   54 => "[B"                                                , // `Java.Interop.JavaSByteArray, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xb6c4749da9477c3a (TaskId:291)
ILLink: 	index   55 => "android/os/Looper"                                 , // `Android.OS.Looper, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xbb84ccbe48f6c18b (TaskId:291)
ILLink: 	index   56 => "java/lang/Object"                                  , // `Java.Lang.Object, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xbf6d427143271cb3 (TaskId:291)
ILLink: 	index   57 => "java/lang/ClassNotFoundException"                  , // `Java.Lang.ClassNotFoundException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xc00f4c2f11efdcff (TaskId:291)
ILLink: 	index   58 => "mono/java/lang/RunnableImplementor"                , // `Java.Lang.Thread+RunnableImplementor, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xc2a8e50a5f08afc6 (TaskId:291)
ILLink: 	index   59 => "java/util/Collection"                              , // `Android.Runtime.JavaCollection, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xca35caf567cfa745 (TaskId:291)
ILLink: 	index   60 => "android/app/Application"                           , // `Android.App.Application, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xcc306823503920e9 (TaskId:291)
ILLink: 	index   61 => "java/lang/Double"                                  , // `Java.Lang.Double, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xd1b288a9c7bb8f53 (TaskId:291)
ILLink: 	index   62 => "[D"                                                , // `Java.Interop.JavaDoubleArray, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xd2fc750314fd2213 (TaskId:291)
ILLink: 	index   63 => "java/lang/UnsupportedOperationException"           , // `Java.Lang.UnsupportedOperationException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xdd812f1d4afa427b (TaskId:291)
ILLink: 	index   64 => "[Ljava/lang/Object;"                               , // `Java.Interop.JavaArray`1, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xdfabd9351f4351a6 (TaskId:291)
ILLink: 	index   65 => "java/util/function/Consumer"                       , // `Java.Util.Functions.IConsumer, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xe024b538ad65ea66 (TaskId:291)
ILLink: 	index   66 => "java/lang/NoClassDefFoundError"                    , // `Java.Lang.NoClassDefFoundError, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xe0446bf91fb0c2dd (TaskId:291)
ILLink: 	index   67 => "java/nio/channels/FileChannel"                     , // `Java.Nio.Channels.FileChannel, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xe1b3c5871398eb28 (TaskId:291)
ILLink: 	index   68 => "net/dot/jni/ManagedPeer"                           , // `Java.Interop.ManagedPeer, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xe5abbaa9de37d34b (TaskId:291)
ILLink: 	index   69 => "java/lang/Long"                                    , // `Java.Lang.Long, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xeb82145dcac4c559 (TaskId:291)
ILLink: 	index   70 => "java/nio/channels/spi/AbstractInterruptibleChannel", // `Java.Nio.Channels.Spi.AbstractInterruptibleChannel, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xed49ed70aa9be1b3 (TaskId:291)
ILLink: 	index   71 => "java/io/FileInputStream"                           , // `Java.IO.FileInputStream, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xef2f2996a1d369cc (TaskId:291)
ILLink: 	index   72 => "java/lang/IndexOutOfBoundsException"               , // `Java.Lang.IndexOutOfBoundsException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xf11f22a6441fcfbc (TaskId:291)
ILLink: 	index   73 => "java/util/AbstractList"                            , // `Java.Util.AbstractList, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xf6992bc6c5609046 (TaskId:291)
ILLink: 	index   74 => "java/util/AbstractCollection"                      , // `Java.Util.AbstractCollection, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xf9ad79a231c20217 (TaskId:291)
ILLink: 	index   75 => "java/util/HashSet"                                 , // `Android.Runtime.JavaSet, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xfbe9bfa5cc50fed6 (TaskId:291)
ILLink: 	index   76 => "java/lang/Runnable"                                , // `Java.Lang.IRunnable, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0xfd2b1a3de667eb51 (TaskId:291)
ILLink: .NET -> JNI mappings (TaskId:291)
ILLink: Generated field Microsoft.Android.Runtime.TypeMapping.s_get_TypeNameHashes_data contains 98 hashes: (TaskId:291)
ILLink: 	0x242f4a673f183d1  //    0: Java.Lang.IndexOutOfBoundsException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x6ae40bcde2b6f61  //    1: Android.Content.ContextInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x7c2b62d20a668dd  //    2: Java.Util.ArrayList, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xe8674a6917e6774  //    3: Java.Interop.JavaInt16Array, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x132055d1acecc87d //    4: Android.Runtime.JavaList`1, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x1344326d070b5f4b //    5: Java.Lang.NullPointerException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x13fa34d4181f58e7 //    6: Java.Util.Functions.IConsumerInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x15a7c8d79f3fc11f //    7: Java.Lang.ClassLoader, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x169f1af934b8cfcc //    8: Java.Lang.String, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x17c5a9be00f31430 //    9: Java.Lang.Double, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x18562cfa0a3303fd //   10: Java.Lang.UnsupportedOperationException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x1a523e8f440f35b7 //   11: Android.Runtime.JavaCollection, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x1b0ebc8de4276850 //   12: android_identity.MainActivity, android-identity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null (TaskId:291)
ILLink: 	0x1b229d4bd0b6f14f //   13: Java.Lang.LinkageError, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x1d5a269438192953 //   14: Java.Lang.Exception, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x1df0d9577504d9f8 //   15: Java.Nio.Channels.FileChannel, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x20744f0a191e9f89 //   16: Java.Nio.Channels.Spi.AbstractInterruptibleChannelInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x20d4d554200f2e31 //   17: Java.Lang.ICharSequenceInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x20d7ca23570fef4a //   18: Android.Runtime.JavaProxyThrowable, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x21e2ffdbecd6590b //   19: Java.Lang.Float, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x227061c7cfa9d45d //   20: Java.Interop.TypeManager+JavaTypeManager, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x2813182aa5e0311b //   21: Android.Runtime.JavaDictionary, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x283254dbad51982d //   22: Java.Lang.Character, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x289591b47367e763 //   23: Java.Nio.Channels.Spi.AbstractInterruptibleChannel, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x2b169824fb3c0636 //   24: Java.Util.AbstractCollection, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x2d601440e89d193f //   25: Java.Util.Functions.IConsumer, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x2da7536bef21700e //   26: Java.Interop.JavaException, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x30ee48c56de49882 //   27: Java.Interop.JavaProxyObject, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x31fcba474c2f3b6d //   28: Java.Interop.ManagedPeer, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x339b233afe2a3434 //   29: Java.Lang.NumberInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x386176afae6775ce //   30: Java.Lang.IRunnableInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x3e31202c2ec24ae0 //   31: Android.Content.Context, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x41b76d8d4b2d1db9 //   32: Java.Util.IIteratorInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x462c98eb5ae580cd //   33: Java.Nio.Channels.FileChannelInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x465c42f088365d5e //   34: Java.IO.OutputStream, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x48a63a89cfee545f //   35: Android.Runtime.JavaList, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x48a7395812918328 //   36: Java.Lang.Thread, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x4d541bdae48a0a0d //   37: Java.IO.File, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x4f114fe3f00bb822 //   38: Java.Lang.ClassLoaderInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x5528374a4c10855f //   39: Java.Lang.Error, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x5629d92b9b33edec //   40: Java.Interop.JavaCharArray, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x581ae993a1efcf97 //   41: Java.Lang.ClassCastException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x5a4ada19da0c0f6a //   42: Android.OS.BaseBundle, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x5b4a99c45538d0fb //   43: Java.Lang.Object, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x616be97b96b0a5c0 //   44: Java.Lang.Number, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x6a19cef6ca08647a //   45: Java.Interop.JavaInt64Array, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x6d5ed53e75e9d399 //   46: Android.App.Activity, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x7a8c50c5fdf8a299 //   47: Java.Interop.JavaObjectArray`1, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x7ae9af96792f22de //   48: Java.IO.InputStream, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x81fe0ee978be6780 //   49: Java.Lang.Long, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x88a12107f88ba9a7 //   50: Java.Interop.JavaObject, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x88e8e07a5df27377 //   51: Android.Runtime.JavaObject, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x8ab15b52718902fb //   52: Java.Lang.Byte, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x8c6ec4c34e2665dc //   53: Java.Util.AbstractListInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x8d07dbd1db57e669 //   54: Java.Lang.ReflectiveOperationException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x8ec7d9111ff623a6 //   55: Java.Interop.JavaArray`1, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x9235b276a408874e //   56: Java.Interop.JavaDoubleArray, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x934a702e6824404a //   57: Java.Lang.Thread+RunnableImplementor, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x94cb4a1263136fbb //   58: Java.Util.IIterator, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x94cf870d3871184e //   59: Java.Interop.JavaBooleanArray, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x953cc6164994ad8d //   60: Java.Interop.JavaSByteArray, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x96b509ac22933e08 //   61: Android.OS.PersistableBundle, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x97c6d5d740565298 //   62: Java.Interop.JavaSingleArray, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x99e94fe9bd773624 //   63: Android.Content.ContextWrapper, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0x9de9600783138021 //   64: Java.Lang.RuntimeException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xa1d4b3bd56cd231c //   65: Android.OS.Looper, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xa1de574fb2179092 //   66: Java.Util.AbstractCollectionInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xa364b41824d64650 //   67: Java.IO.IOException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xa4a869dd34359d43 //   68: Java.Lang.IllegalArgumentException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xa4f3c7b6284df8ce //   69: Java.Interop.JavaPrimitiveArray`1, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xa8ae49decfe4e4bd //   70: Android.Runtime.JavaSet, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xa8d0447ff05b6f01 //   71: Java.IO.FileInputStream, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xab4cc1a728eaa2db //   72: Java.Lang.Class, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xafc03f28c9913823 //   73: Java.Interop.JavaInt32Array, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xb80c50f4dd98ede3 //   74: Java.Lang.IllegalStateException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xb8112eb206ffbb78 //   75: Java.Lang.Integer, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xbaf0c10d01576861 //   76: Java.Lang.ThreadGroup, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xbb5ad67fa65c24a4 //   77: Android.Runtime.OutputStreamAdapter, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xbefa823585668458 //   78: Android.Views.ContextThemeWrapper, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xc0b66ffbf2ec8da7 //   79: Java.Lang.NoClassDefFoundError, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xc4d562896b9d53f3 //   80: Java.Lang.Short, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xcaea90feb62c9567 //   81: Android.OS.Bundle, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xcd4dfba28c201ba1 //   82: Java.Interop.JavaProxyThrowable, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xcef500cfa7a19d37 //   83: Java.Lang.ClassNotFoundException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xd337632cc38253a2 //   84: Android.Runtime.JavaDictionary`2, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xd78bb459112681e0 //   85: Android.OS.Handler, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xd7d2f681d42175c1 //   86: Android.Runtime.JavaSet`1, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xd97b69d8d01d0c10 //   87: Java.Util.AbstractList, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xda1d41d8a6ca2367 //   88: Java.IO.InputStreamInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xdbdcdfd8f6d89240 //   89: Java.Lang.Boolean, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xdda94dc5b92a59c0 //   90: Java.IO.FileDescriptor, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xe312e02f42c91db0 //   91: Java.Lang.StackTraceElement, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xe554106129b376fe //   92: Android.App.Application, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xe7db623ffd0dd84e //   93: Java.IO.OutputStreamInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xeba256b5da4f2d6d //   94: Android.Runtime.JavaCollection`1, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xef2efa58a51bb883 //   95: Java.Lang.IRunnable, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xf022ead589aa37d2 //   96: Android.Runtime.InputStreamAdapter, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: 	0xf983b71c7661b27c //   97: Java.Lang.Throwable, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (TaskId:291)
ILLink: Generated method Microsoft.Android.Runtime.TypeMapping.GetJavaClassNameByIndex contains 98 mappings: (TaskId:291)
ILLink: 	index    0 => "java/lang/IndexOutOfBoundsException"               , // `Java.Lang.IndexOutOfBoundsException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x0242f4a673f183d1 (TaskId:291)
ILLink: 	index    1 => "android/content/Context"                           , // `Android.Content.ContextInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x06ae40bcde2b6f61 (TaskId:291)
ILLink: 	index    2 => "java/util/ArrayList"                               , // `Java.Util.ArrayList, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x07c2b62d20a668dd (TaskId:291)
ILLink: 	index    3 => "[S"                                                , // `Java.Interop.JavaInt16Array, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x0e8674a6917e6774 (TaskId:291)
ILLink: 	index    4 => "java/util/ArrayList"                               , // `Android.Runtime.JavaList`1, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x132055d1acecc87d (TaskId:291)
ILLink: 	index    5 => "java/lang/NullPointerException"                    , // `Java.Lang.NullPointerException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x1344326d070b5f4b (TaskId:291)
ILLink: 	index    6 => "java/util/function/Consumer"                       , // `Java.Util.Functions.IConsumerInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x13fa34d4181f58e7 (TaskId:291)
ILLink: 	index    7 => "java/lang/ClassLoader"                             , // `Java.Lang.ClassLoader, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x15a7c8d79f3fc11f (TaskId:291)
ILLink: 	index    8 => "java/lang/String"                                  , // `Java.Lang.String, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x169f1af934b8cfcc (TaskId:291)
ILLink: 	index    9 => "java/lang/Double"                                  , // `Java.Lang.Double, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x17c5a9be00f31430 (TaskId:291)
ILLink: 	index   10 => "java/lang/UnsupportedOperationException"           , // `Java.Lang.UnsupportedOperationException, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x18562cfa0a3303fd (TaskId:291)
ILLink: 	index   11 => "java/util/Collection"                              , // `Android.Runtime.JavaCollection, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x1a523e8f440f35b7 (TaskId:291)
ILLink: 	index   12 => "crc6441ef2972864c2db2/MainActivity"                , // `android_identity.MainActivity, android-identity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null` hash=0x1b0ebc8de4276850 (TaskId:291)
ILLink: 	index   13 => "java/lang/LinkageError"                            , // `Java.Lang.LinkageError, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x1b229d4bd0b6f14f (TaskId:291)
ILLink: 	index   14 => "java/lang/Exception"                               , // `Java.Lang.Exception, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x1d5a269438192953 (TaskId:291)
ILLink: 	index   15 => "java/nio/channels/FileChannel"                     , // `Java.Nio.Channels.FileChannel, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x1df0d9577504d9f8 (TaskId:291)
ILLink: 	index   16 => "java/nio/channels/spi/AbstractInterruptibleChannel", // `Java.Nio.Channels.Spi.AbstractInterruptibleChannelInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x20744f0a191e9f89 (TaskId:291)
ILLink: 	index   17 => "java/lang/CharSequence"                            , // `Java.Lang.ICharSequenceInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x20d4d554200f2e31 (TaskId:291)
ILLink: 	index   18 => "android/runtime/JavaProxyThrowable"                , // `Android.Runtime.JavaProxyThrowable, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x20d7ca23570fef4a (TaskId:291)
ILLink: 	index   19 => "java/lang/Float"                                   , // `Java.Lang.Float, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x21e2ffdbecd6590b (TaskId:291)
ILLink: 	index   20 => "mono/android/TypeManager"                          , // `Java.Interop.TypeManager+JavaTypeManager, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x227061c7cfa9d45d (TaskId:291)
ILLink: 	index   21 => "java/util/HashMap"                                 , // `Android.Runtime.JavaDictionary, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x2813182aa5e0311b (TaskId:291)
ILLink: 	index   22 => "java/lang/Character"                               , // `Java.Lang.Character, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x283254dbad51982d (TaskId:291)
ILLink: 	index   23 => "java/nio/channels/spi/AbstractInterruptibleChannel", // `Java.Nio.Channels.Spi.AbstractInterruptibleChannel, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x289591b47367e763 (TaskId:291)
ILLink: 	index   24 => "java/util/AbstractCollection"                      , // `Java.Util.AbstractCollection, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x2b169824fb3c0636 (TaskId:291)
ILLink: 	index   25 => "java/util/function/Consumer"                       , // `Java.Util.Functions.IConsumer, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x2d601440e89d193f (TaskId:291)
ILLink: 	index   26 => "java/lang/Throwable"                               , // `Java.Interop.JavaException, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x2da7536bef21700e (TaskId:291)
ILLink: 	index   27 => "net/dot/jni/internal/JavaProxyObject"              , // `Java.Interop.JavaProxyObject, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x30ee48c56de49882 (TaskId:291)
ILLink: 	index   28 => "net/dot/jni/ManagedPeer"                           , // `Java.Interop.ManagedPeer, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x31fcba474c2f3b6d (TaskId:291)
ILLink: 	index   29 => "java/lang/Number"                                  , // `Java.Lang.NumberInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x339b233afe2a3434 (TaskId:291)
ILLink: 	index   30 => "java/lang/Runnable"                                , // `Java.Lang.IRunnableInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x386176afae6775ce (TaskId:291)
ILLink: 	index   31 => "android/content/Context"                           , // `Android.Content.Context, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x3e31202c2ec24ae0 (TaskId:291)
ILLink: 	index   32 => "java/util/Iterator"                                , // `Java.Util.IIteratorInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x41b76d8d4b2d1db9 (TaskId:291)
ILLink: 	index   33 => "java/nio/channels/FileChannel"                     , // `Java.Nio.Channels.FileChannelInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x462c98eb5ae580cd (TaskId:291)
ILLink: 	index   34 => "java/io/OutputStream"                              , // `Java.IO.OutputStream, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x465c42f088365d5e (TaskId:291)
ILLink: 	index   35 => "java/util/ArrayList"                               , // `Android.Runtime.JavaList, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x48a63a89cfee545f (TaskId:291)
ILLink: 	index   36 => "java/lang/Thread"                                  , // `Java.Lang.Thread, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065` hash=0x48a7395812918328 (TaskId:291)
ILLink: 	index   37 => "java/io/File"                                      , // `Java.IO.File, Mono.Android, Version=0.0.0.0, Culture=neutral, Publ…
@simonrozsival
Copy link
Member Author

@jonpryor I renamed the methods, properties, and local variables. The names are now more descriptive. I chose to stick to names such as typeName and GetJniNameByTypeNameHashIndex instead of managedTypeName and GetJniNameByManagedTypeNameHashIndex since I believe it's clear that we're talking about managed types as counterparts of JNI names and adding managed to all the names didn't seem helpful. Please have anogher look.

@jonpryor
Copy link
Contributor

Not sure what's up with GitHub, but devops is now green: https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=11218551&view=results

@jonpryor jonpryor merged commit b11471b into main Mar 19, 2025
55 of 58 checks passed
@jonpryor jonpryor deleted the dev/simonrozsival/improve-managed-typemap branch March 19, 2025 02:15
@github-actions github-actions bot locked and limited conversation to collaborators Apr 18, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants