Skip to content
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

VS 16.6.0 Prev 1.0 App crashes on "Cannot create instance of type ... no Java peer type found" after incremental build #4415

Closed
gmck opened this issue Mar 18, 2020 · 43 comments · Fixed by #4487
Assignees
Labels
Area: App Runtime Issues in `libmonodroid.so`. regression

Comments

@gmck
Copy link

gmck commented Mar 18, 2020

Sometimes after even just a small change in code. Click deploy, builds and deploys with no errors and then crashes at runtime. This is just a sample with this SettingsFragment, but it is regularly happening on two projects I'm working on. Clean, rebuild and deploy and it is good again. Not dissimilar to the other problems reported with earlier previews where you had to clean/build/deploy way too much.

2020-03-18 16:53:03.399 12333-12333/com.glmsoftware.obdnowproto E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.glmsoftware.obdnowproto, PID: 12333
    android.runtime.JavaProxyThrowable: System.NotSupportedException: Cannot create instance of type 'com.glmsoftware.OBDNowProto.SettingsFragmentCompat': no Java peer type found.
      at Java.Interop.JniPeerMembers+JniInstanceMethods..ctor (System.Type declaringType) [0x0004b] in <e3e4dfa992a7411b85acfe193481be3e>:0 
      at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructorsForType (System.Type declaringType) [0x00031] in <e3e4dfa992a7411b85acfe193481be3e>:0 
      at Java.Interop.JniPeerMembers+JniInstanceMethods.StartCreateInstance (System.String constructorSignature, System.Type declaringType, Java.Interop.JniArgumentValue* parameters) [0x00038] in <e3e4dfa992a7411b85acfe193481be3e>:0 
      at AndroidX.Preference.PreferenceFragmentCompat..ctor () [0x00034] in <005e3ae6340747e1aea6d08b095cf286>:0 
      at com.glmsoftware.OBDNowProto.SettingsFragmentCompat..ctor () [0x00026] in <a8dbee4be1674aa08cce57b50f21e347>:0 
      at com.glmsoftware.OBDNowProto.SettingsActivity.OnCreate (Android.OS.Bundle bundle) [0x00083] in <a8dbee4be1674aa08cce57b50f21e347>:0 
      at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00011] in <c56099afccf04721853684f376a89527>:0 
        at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.3(intptr,intptr,intptr)
        at crc64596a13587a898911.SettingsActivity.n_onCreate(Native Method)
        at crc64596a13587a898911.SettingsActivity.onCreate(SettingsActivity.java:40)
        at android.app.Activity.performCreate(Activity.java:7825)
        at android.app.Activity.performCreate(Activity.java:7814)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
@gmck gmck added the Area: App Runtime Issues in `libmonodroid.so`. label Mar 18, 2020
@gugavaro
Copy link
Contributor

@dellis1972 who should take a look on this?

@grendello
Copy link
Contributor

grendello commented Mar 19, 2020

@gmck can you provide a full logcat of a failed session, obtained by issuing these commands from command prompt:

adb shell setprop debug.mono.log default,assembly,timing=bare
adb logcat -c
[run the application here]
adb logcat -d > log.txt

I'm assigning this to @dellis1972 and @jonathanpeppers for now since it happens on rebuilds, but it might just as well be an issue with the generator or typemaps. It would be best if you were able to provide a small repro application in addition to the logcat output, if at all possible. Thanks!

@grendello grendello added this to the Under Consideration milestone Mar 19, 2020
@grendello grendello added the need-info Issues that need more information from the author. label Mar 19, 2020
@jonathanpeppers
Copy link
Member

@gmck I think you might find you need to Clean if you open a project in 16.6 preview 1 that was previously built with 16.4 or 16.5. After the first Clean it should be working, though.

We will hopefully fix this in the next preview via: #4360

@gmck
Copy link
Author

gmck commented Mar 19, 2020

@jonathanpeppers I can assure you it was cleaned when I first opened it in 16.6.0 1.0. Mate, I do a lot of cleaning. My clean menu item is probably worn out!!!

#4360 looks like it covers all this stuff.

The actual exception above was for real and nothing to do with cleaning. The exception is because of Android's wonderful new Navigation component (even 2.2.1) just cannot handle a PreferenceFragmentCompat fragment. According to their nav_graph and their docs all fragments in a nav_graph require tools:layout. Well, PrefereenceFragmentCompat doesn't use a layout. OnCreatePreferences either uses AddPreferencesFromResources or SetPreferencesFromResource, therefore no layout and I believe that is what is causing the exception.

So if you use preferences in your app, it is not going to a their "holy grail" Single Activity app. Just for the Android Xamariners who haven't tried it. In a NavComponent app you can still use an activity just like you always did with StartActivity(intent).

You can even set up the activity in the nav_graph, so you can launch it directly via navController.Navigate(Resource.Id.action_settings). However, to make it work in the nav_graph, there is a specific requirement Xamarin requirement.

What you can't do in the nav_graph as you would do in Android Studio
<activity
android:id="@+id/action_settings"
android:name="com.companyname.appname.activities.SettingsActivity
android:label ="Settings"
tools:layout="@layout/activity_settings"/>

What to do with Xamarin.Android
Replace the android:name with either

android:name="com.companyname.appname.activities.crc645....11.SettingsActivity
or just
android:name="crc645....11.SettingsActivity"

You can get your particular "crc...." of your activity from the obj/debug/100/manifest/AndroidManifest.xml file

@grendello I can provide you with this prototype app, because I think it covers most of the problems I've been experiencing during the last month, especially in relation to #4360. However, I can't upload it here, could you advise how to get it to you.

@jonathanpeppers
Copy link
Member

@gmck you should use:

[Register ("com.companyname.appname.activities.SettingsActivity")]
public class SettingsActivity ...

Then you don't have to lookup what the crc value is.

@grendello
Copy link
Contributor

grendello commented Mar 19, 2020

@gmck a link to a repository or an archive will do :) (unless it's confidential, in which case please mail it to @jonathanpeppers and me at our GH emails)

@gmck
Copy link
Author

gmck commented Mar 19, 2020

Thanks, Jonathan didn't know that.

Wish I'd known that a couple of days ago, that's one day I'm never getting back figuring that one out.

I don't want to make it public, so can I have an email address.

@gmck
Copy link
Author

gmck commented Mar 19, 2020

oops..
@grendello I don't want to make it public, so can I have an email address.

@brendanzagaeski
Copy link
Contributor

brendanzagaeski commented Mar 20, 2020

I was able to put together steps to reproduce from other reports of this issue.

Steps to reproduce

  1. Download the following sample: https://docs.microsoft.com/samples/xamarin/xamarin-forms-samples/customrenderers-map-circle/
  2. msbuild -restore -t:Install Droid\MapOverlay.Droid.csproj
  3. Update the timestamp of Droid\MainActivity.cs. For example, open the file in Notepad and save it.
  4. msbuild -restore -t:Install Droid\MapOverlay.Droid.csproj
  5. Launch the application by tapping the icon on the device.

Expected behavior

The application launches successfully.

Actual behavior with Xamarin.Android 10.2.100.7

The application crashes with the exception mentioned in the description of this issue. Excerpt from my local repro:

UNHANDLED EXCEPTION:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NotSupportedException: Cannot create instance of type 'MapOverlay.Droid.CustomMapRenderer': no Java peer type found.
  at Java.Interop.JniPeerMembers+JniInstanceMethods..ctor (System.Type declaringType) [0x0004b] in <e3e4dfa992a7411b85acfe193481be3e>:0 
  at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructorsForType (System.Type declaringType) [0x00031] in 

Actual behavior with Xamarin.Android 10.3.0.28

The application gets stuck in a crash and restart loop on the following exception:

Unhandled Exception:
System.MissingMethodException: Method not found: void .CreationOptions.set_JniAddNativeMethodRegistrationAttributePresent
(bool)
  at Android.Runtime.AndroidRuntime..ctor (System.IntPtr jnienv, System.IntPtr vm, System.Boolean allocNewObjectSupported, System.IntPtr classLoader, System.IntPtr classLoader_loadClass, System.Boolean jniAddNativeMethodRegistrationAttributePresent) [0x00000] in <003b7b299c604c84becae25f1bd49871>:0 
  at Android.Runtime.JNIEnv.Initialize (Android.Runtime.JnienvInitializeArgs* args) [0x000f9] in <003b7b299c604c84becae25f1bd49871>:0 
[ERROR] FATAL UNHANDLED EXCEPTION: System.MissingMethodException: Method not found: void .CreationOptions.set_JniAddNativeMethodRegistrationAttributePresent(bool)
  at Android.Runtime.AndroidRuntime..ctor (System.IntPtr jnienv, System.IntPtr vm, System.Boolean allocNewObjectSupported, System.IntPtr classLoader, System.IntPtr classLoader_loadClass, System.Boolean jniAddNativeMethodRegistrationAttributePresent) [0x00000] in <003b7b299c604c84becae25f1bd49871>:0 
  at Android.Runtime.JNIEnv.Initialize (Android.Runtime.JnienvInitializeArgs* args) [0x000f9] in <003b7b299c604c84becae25f1bd49871>:0 

(This is probably a separate bug, but I'm not sure if it means the issue from 10.2.100.7 is fixed or just hidden, for example if this new issue happens earlier in the application init.)

Version information

  • Xamarin.Android SDK 10.2.100.7 (d16-6@69561a7)

  • Xamarin.Android SDK 10.3.0.28 (d16-6/670668f)

Log files

MSBuild diagnostic build output for the second build, and the adb logcat output on 10.2.100.7:
logs_10201007.zip

Just the adb logcat on 10.3.0.28:
adblogcat_103028.zip

@brendanzagaeski
Copy link
Contributor

@brendanzagaeski brendanzagaeski removed the need-info Issues that need more information from the author. label Mar 20, 2020
@brendanzagaeski
Copy link
Contributor

To be thorough, I did a quick verification of Xamarin.Android 10.2.0.100, and, as expected, the app launches successfully after the second build in that case.

@brendanzagaeski brendanzagaeski changed the title VS 16.6.0 Prev 1.0 Very flaky compiling/deploying VS 16.6.0 Prev 1.0 App crashes on "Cannot create instance of type ... no Java peer type found" after incremental build Mar 20, 2020
@jonathanpeppers
Copy link
Member

@grendello @brendanzagaeski I hit this crash on the first build of this app:
https://docs.microsoft.com/samples/xamarin/xamarin-forms-samples/customrenderers-map-circle/

03-20 08:39:27.088 21460 21460 E mono    : Unhandled Exception:
03-20 08:39:27.088 21460 21460 E mono    : System.MissingMethodException: Method not found: void .CreationOptions.set_JniAddNativeMethodRegistrationAttributePresent(bool)
03-20 08:39:27.088 21460 21460 E mono    :   at Android.Runtime.AndroidRuntime..ctor (System.IntPtr jnienv, System.IntPtr vm, System.Boolean allocNewObjectSupported, System.IntPtr classLoader, System.IntPtr class
Loader_loadClass, System.Boolean jniAddNativeMethodRegistrationAttributePresent) [0x00000] in <9208d5fd0c8c43b7a00f304ba0f7c041>:0
03-20 08:39:27.088 21460 21460 E mono    :   at Android.Runtime.JNIEnv.Initialize (Android.Runtime.JnienvInitializeArgs* args) [0x000ed] in <9208d5fd0c8c43b7a00f304ba0f7c041>:0
03-20 08:39:27.090 21460 21460 E mono-rt : [ERROR] FATAL UNHANDLED EXCEPTION: System.MissingMethodException: Method not found: void .CreationOptions.set_JniAddNativeMethodRegistrationAttributePresent(bool)
03-20 08:39:27.090 21460 21460 E mono-rt :   at Android.Runtime.AndroidRuntime..ctor (System.IntPtr jnienv, System.IntPtr vm, System.Boolean allocNewObjectSupported, System.IntPtr classLoader, System.IntPtr class
Loader_loadClass, System.Boolean jniAddNativeMethodRegistrationAttributePresent) [0x00000] in <9208d5fd0c8c43b7a00f304ba0f7c041>:0
03-20 08:39:27.090 21460 21460 E mono-rt :   at Android.Runtime.JNIEnv.Initialize (Android.Runtime.JnienvInitializeArgs* args) [0x000ed] in <9208d5fd0c8c43b7a00f304ba0f7c041>:0

@jonathanpeppers
Copy link
Member

jonathanpeppers commented Mar 20, 2020

After playing some more, I can't reproduce this first error I got ☝️ .

But if you do this:

> touch .\Droid\MainActivity.cs

Then build again.

You get a new MapOverlay.Droid.dll with new MVID. So we get a new libxamarin-app.so native library.

But then this happened:

Skipping target "_CreateBaseApk" because all output files are up-to-date with respect to the input files.

This is wrong, but if we fix this it will severely impact incremental build times... We would effectively be creating a new APK, signing it, and installing it every time you change C# code.

The above problem goes away if you put <Deterministic>True</Deterministic> in the app's csproj. Because Roslyn will generate an identical assembly on every build. $(Deterministic) is set in the latest templates, so this is why we probably missed this in QA.

@grendello any ideas around this? Trying to think how we can ship ce2bc68 and not break anyone.

@jonathanpeppers
Copy link
Member

@jonpryor any ideas? Should we think about making $(Deterministic) required?

@grendello
Copy link
Contributor

@jonathanpeppers the first crash you got is because, somehow, the app has Java.Interop.dll that's too old. The property mentioned in the error message got added in this commit.
Regarding $(Deterministic) - it is necessary only if the assemblies are for some reason modified after the typemaps are generated. So, perhaps, on incremental builds we should always set it to true?

@jonathanpeppers
Copy link
Member

@gmck can you put <Deterministic>True</Deterministic> in your main app's .csproj to see if the problem goes away for you?

Just add it at the top at the end of the first </PropertyGroup>.

@gmck
Copy link
Author

gmck commented Mar 20, 2020

@grendello You referred to GH email addresses for Jonathan and yourself. Could you please indicate where I can find those addresses and I'll provide you with a link

@grendello
Copy link
Contributor

@gmck click on our avatars :)

@gmck
Copy link
Author

gmck commented Mar 20, 2020

@grendello Thanks.
So you don't mean an actual GH address. eg. your twistedcode.net address is what is required

@Lau69
Copy link

Lau69 commented Mar 22, 2020

Hello
I have the same issue : VS 16.6.0 Prev 1.0 App crashes on "Cannot create instance of type ... no Java peer type found" after incremental build
with this simple project (Default Xamarin Android project with Api 28) :

public class JavaClass : Java.Lang.Object
{
	/*
		reference assembly Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065
		C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\Common7\IDE\ReferenceAssemblies\Microsoft\Framework\MonoAndroid\v9.0\Mono.Android.dll
	*/
}

public partial class App : Xamarin.Forms.Application
{
	public App()
	{
		this.InitializeComponent();
		this.MainPage = new MainPage();
	}

	protected override void OnStart()
	{
		try
		{
			var TestNew = new JavaClass();
		}
		catch( System.Exception ex )
		{
			System.Diagnostics.Debug.WriteLine( ex );
			/*
				1) Visual Studio Start Debug	=> Application display "CrashTest"
				2) Visual Studio Stop Debug
				3) Modify file for force rebuild
				4) Visual Studio Start Debug	=> Exception
				5) Visual Studio Stop Debug
				6) Visual Studio Clean Solution
				7) Visual Studio Start Debug	=> Application display "CrashTest"

				System.NotSupportedException: Cannot create instance of type 'CrashTest.JavaClass': no Java peer type found.
				  at Java.Interop.JniPeerMembers+JniInstanceMethods..ctor (System.Type declaringType) [0x0004b] in <e3e4dfa992a7411b85acfe193481be3e>:0 
				  at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructorsForType (System.Type declaringType) [0x00031] in <e3e4dfa992a7411b85acfe193481be3e>:0 
				  at Java.Interop.JniPeerMembers+JniInstanceMethods.StartCreateInstance (System.String constructorSignature, System.Type declaringType, Java.Interop.JniArgumentValue* parameters) [0x00038] in <e3e4dfa992a7411b85acfe193481be3e>:0 
				  at Java.Lang.Object..ctor () [0x00034] in <03cab052cc7c4408a5b6127cbc405113>:0 
				  at CrashTest.JavaClass..ctor () <0x7276285750 + 0x0003b> in <1a8014a9b10847c2a184e69908dd94c4>:0 
				  at CrashTest.App.OnStart () [0x00002] in C:\Users\Famille\source\repos\CrashTest\CrashTest\CrashTest\App.xaml.cs:23
			*/
		}
	}
}

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="CrashTest.MainPage">

	<Label Text="CrashTest" />

</ContentPage>

I change to Api 29 and the exception disappears

@Lau69
Copy link

Lau69 commented Mar 25, 2020

@jonathanpeppers Does this mean that the Visual Studio project creation templates are wrong ?

@jonathanpeppers
Copy link
Member

@Lau69 the template didn't include this did it?

  <ItemGroup>
        <!-- This is wrong -->
	<Reference Include="Mono.Android">
	  <HintPath>..\..\..\..\..\..\..\Program Files (x86)\Microsoft Visual Studio\2019\Preview\Common7\IDE\ReferenceAssemblies\Microsoft\Framework\MonoAndroid\v9.0\Mono.Android.dll</HintPath>
	</Reference>
  </ItemGroup>

@Lau69
Copy link

Lau69 commented Mar 25, 2020

@jonathanpeppers You are right. It's not the template. I was not vigilant enough, thank you

grendello added a commit to grendello/xamarin-android that referenced this issue Mar 31, 2020
Fixes: dotnet#4415
Context: dotnet@ce2bc68

This commit partially reverts ce2bc68
in the sense that it restores the use of type names for Java-to-Managed
and Managed-to-Java type lookups for **Debug** builds only.

The reason for the change is that in order for the MVID and type token
based lookups to work we need two things:

  - for the MVID to remain unchanged in each mapped assembly
	- for the type token to remain unchanged in each mapped assembly

However, in incremental builds neither of the above requirements is
met **unless** the application is fully rebuilt and, thus, the typemaps
are regenerated from scratch, which obviously doesn't sit well with the
incremental nature of incremental builds :)

With MVID/token id maps, every change to any source code that's built
into a mapped assembly, may cause the assembly to change its MVID and
renaming of any type, removing or adding a type, will rearrange the type
definition table in the resulting assembly, thus changing the type token
ids (which are basically offsets into the type definition table in the
PE executable). This is what may cause an app to crash on the runtime
with an exception similar to:

    android.runtime.JavaProxyThrowable: System.NotSupportedException: Cannot create instance of type 'com.glmsoftware.OBDNowProto.SettingsFragmentCompat': no Java peer type found.
      at Java.Interop.JniPeerMembers+JniInstanceMethods..ctor (System.Type declaringType) [0x0004b] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructorsForType (System.Type declaringType) [0x00031] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.StartCreateInstance (System.String constructorSignature, System.Type declaringType, Java.Interop.JniArgumentValue* parameters) [0x00038] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at AndroidX.Preference.PreferenceFragmentCompat..ctor () [0x00034] in <005e3ae6340747e1aea6d08b095cf286>:0
      at com.glmsoftware.OBDNowProto.SettingsFragmentCompat..ctor () [0x00026] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at com.glmsoftware.OBDNowProto.SettingsActivity.OnCreate (Android.OS.Bundle bundle) [0x00083] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00011] in <c56099afccf04721853684f376a89527>:0
        at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.3(intptr,intptr,intptr)
        at crc64596a13587a898911.SettingsActivity.n_onCreate(Native Method)
        at crc64596a13587a898911.SettingsActivity.onCreate(SettingsActivity.java:40)
        at android.app.Activity.performCreate(Activity.java:7825)
        at android.app.Activity.performCreate(Activity.java:7814)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

Thus, we need to revert the Debug builds to the variation of the old
string-based type name mapping. This commit implements it in a slightly
leaner form than it was implemented before
ce2bc68 landed in that only one copy of
each set of type names (Java and managed) is maintained in both memory
and on disk, at a tiny (sub millisecond) expense at the run time to fix
up pointers between the two tables.
grendello added a commit to grendello/xamarin-android that referenced this issue Mar 31, 2020
Fixes: dotnet#4415
Context: dotnet@ce2bc68

This commit partially reverts ce2bc68
in the sense that it restores the use of type names for Java-to-Managed
and Managed-to-Java type lookups for **Debug** builds only.

The reason for the change is that in order for the MVID and type token
based lookups to work we need two things:

  - for the MVID to remain unchanged in each mapped assembly
  - for the type token to remain unchanged in each mapped assembly

However, in incremental builds neither of the above requirements is
met **unless** the application is fully rebuilt and, thus, the typemaps
are regenerated from scratch, which obviously doesn't sit well with the
incremental nature of incremental builds :)

With MVID/token id maps, every change to any source code that's built
into a mapped assembly, may cause the assembly to change its MVID and
renaming of any type, removing or adding a type, will rearrange the type
definition table in the resulting assembly, thus changing the type token
ids (which are basically offsets into the type definition table in the
PE executable). This is what may cause an app to crash on the runtime
with an exception similar to:

    android.runtime.JavaProxyThrowable: System.NotSupportedException: Cannot create instance of type 'com.glmsoftware.OBDNowProto.SettingsFragmentCompat': no Java peer type found.
      at Java.Interop.JniPeerMembers+JniInstanceMethods..ctor (System.Type declaringType) [0x0004b] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructorsForType (System.Type declaringType) [0x00031] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.StartCreateInstance (System.String constructorSignature, System.Type declaringType, Java.Interop.JniArgumentValue* parameters) [0x00038] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at AndroidX.Preference.PreferenceFragmentCompat..ctor () [0x00034] in <005e3ae6340747e1aea6d08b095cf286>:0
      at com.glmsoftware.OBDNowProto.SettingsFragmentCompat..ctor () [0x00026] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at com.glmsoftware.OBDNowProto.SettingsActivity.OnCreate (Android.OS.Bundle bundle) [0x00083] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00011] in <c56099afccf04721853684f376a89527>:0
        at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.3(intptr,intptr,intptr)
        at crc64596a13587a898911.SettingsActivity.n_onCreate(Native Method)
        at crc64596a13587a898911.SettingsActivity.onCreate(SettingsActivity.java:40)
        at android.app.Activity.performCreate(Activity.java:7825)
        at android.app.Activity.performCreate(Activity.java:7814)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

Thus, we need to revert the Debug builds to the variation of the old
string-based type name mapping. This commit implements it in a slightly
leaner form than it was implemented before
ce2bc68 landed in that only one copy of
each set of type names (Java and managed) is maintained in both memory
and on disk, at a tiny (sub millisecond) expense at the run time to fix
up pointers between the two tables.
grendello added a commit to grendello/xamarin-android that referenced this issue Mar 31, 2020
Fixes: dotnet#4415
Context: dotnet@ce2bc68

This commit partially reverts ce2bc68
in the sense that it restores the use of type names for Java-to-Managed
and Managed-to-Java type lookups for **Debug** builds only.

The reason for the change is that in order for the MVID and type token
based lookups to work we need two things:

  - for the MVID to remain unchanged in each mapped assembly
  - for the type token to remain unchanged in each mapped assembly

However, in incremental builds neither of the above requirements is
met **unless** the application is fully rebuilt and, thus, the typemaps
are regenerated from scratch, which obviously doesn't sit well with the
incremental nature of incremental builds :)

With MVID/token id maps, every change to any source code that's built
into a mapped assembly, may cause the assembly to change its MVID and
renaming of any type, removing or adding a type, will rearrange the type
definition table in the resulting assembly, thus changing the type token
ids (which are basically offsets into the type definition table in the
PE executable). This is what may cause an app to crash on the runtime
with an exception similar to:

    android.runtime.JavaProxyThrowable: System.NotSupportedException: Cannot create instance of type 'com.glmsoftware.OBDNowProto.SettingsFragmentCompat': no Java peer type found.
      at Java.Interop.JniPeerMembers+JniInstanceMethods..ctor (System.Type declaringType) [0x0004b] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructorsForType (System.Type declaringType) [0x00031] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.StartCreateInstance (System.String constructorSignature, System.Type declaringType, Java.Interop.JniArgumentValue* parameters) [0x00038] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at AndroidX.Preference.PreferenceFragmentCompat..ctor () [0x00034] in <005e3ae6340747e1aea6d08b095cf286>:0
      at com.glmsoftware.OBDNowProto.SettingsFragmentCompat..ctor () [0x00026] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at com.glmsoftware.OBDNowProto.SettingsActivity.OnCreate (Android.OS.Bundle bundle) [0x00083] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00011] in <c56099afccf04721853684f376a89527>:0
        at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.3(intptr,intptr,intptr)
        at crc64596a13587a898911.SettingsActivity.n_onCreate(Native Method)
        at crc64596a13587a898911.SettingsActivity.onCreate(SettingsActivity.java:40)
        at android.app.Activity.performCreate(Activity.java:7825)
        at android.app.Activity.performCreate(Activity.java:7814)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

Thus, we need to revert the Debug builds to the variation of the old
string-based type name mapping. This commit implements it in a slightly
leaner form than it was implemented before
ce2bc68 landed in that only one copy of
each set of type names (Java and managed) is maintained in both memory
and on disk, at a tiny (sub millisecond) expense at the run time to fix
up pointers between the two tables.
grendello added a commit to grendello/xamarin-android that referenced this issue Mar 31, 2020
Fixes: dotnet#4415
Context: dotnet@ce2bc68

This commit partially reverts ce2bc68
in the sense that it restores the use of type names for Java-to-Managed
and Managed-to-Java type lookups for **Debug** builds only.

The reason for the change is that in order for the MVID and type token
based lookups to work we need two things:

  - for the MVID to remain unchanged in each mapped assembly
  - for the type token to remain unchanged in each mapped assembly

However, in incremental builds neither of the above requirements is
met **unless** the application is fully rebuilt and, thus, the typemaps
are regenerated from scratch, which obviously doesn't sit well with the
incremental nature of incremental builds :)

With MVID/token id maps, every change to any source code that's built
into a mapped assembly, may cause the assembly to change its MVID and
renaming of any type, removing or adding a type, will rearrange the type
definition table in the resulting assembly, thus changing the type token
ids (which are basically offsets into the type definition table in the
PE executable). This is what may cause an app to crash on the runtime
with an exception similar to:

    android.runtime.JavaProxyThrowable: System.NotSupportedException: Cannot create instance of type 'com.glmsoftware.OBDNowProto.SettingsFragmentCompat': no Java peer type found.
      at Java.Interop.JniPeerMembers+JniInstanceMethods..ctor (System.Type declaringType) [0x0004b] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructorsForType (System.Type declaringType) [0x00031] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.StartCreateInstance (System.String constructorSignature, System.Type declaringType, Java.Interop.JniArgumentValue* parameters) [0x00038] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at AndroidX.Preference.PreferenceFragmentCompat..ctor () [0x00034] in <005e3ae6340747e1aea6d08b095cf286>:0
      at com.glmsoftware.OBDNowProto.SettingsFragmentCompat..ctor () [0x00026] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at com.glmsoftware.OBDNowProto.SettingsActivity.OnCreate (Android.OS.Bundle bundle) [0x00083] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00011] in <c56099afccf04721853684f376a89527>:0
        at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.3(intptr,intptr,intptr)
        at crc64596a13587a898911.SettingsActivity.n_onCreate(Native Method)
        at crc64596a13587a898911.SettingsActivity.onCreate(SettingsActivity.java:40)
        at android.app.Activity.performCreate(Activity.java:7825)
        at android.app.Activity.performCreate(Activity.java:7814)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

Thus, we need to revert the Debug builds to the variation of the old
string-based type name mapping. This commit implements it in a slightly
leaner form than it was implemented before
ce2bc68 landed in that only one copy of
each set of type names (Java and managed) is maintained in both memory
and on disk, at a tiny (sub millisecond) expense at the run time to fix
up pointers between the two tables.
grendello added a commit to grendello/xamarin-android that referenced this issue Apr 1, 2020
Fixes: dotnet#4415
Context: dotnet@ce2bc68

This commit partially reverts ce2bc68
in the sense that it restores the use of type names for Java-to-Managed
and Managed-to-Java type lookups for **Debug** builds only.

The reason for the change is that in order for the MVID and type token
based lookups to work we need two things:

  - for the MVID to remain unchanged in each mapped assembly
  - for the type token to remain unchanged in each mapped assembly

However, in incremental builds neither of the above requirements is
met **unless** the application is fully rebuilt and, thus, the typemaps
are regenerated from scratch, which obviously doesn't sit well with the
incremental nature of incremental builds :)

With MVID/token id maps, every change to any source code that's built
into a mapped assembly, may cause the assembly to change its MVID and
renaming of any type, removing or adding a type, will rearrange the type
definition table in the resulting assembly, thus changing the type token
ids (which are basically offsets into the type definition table in the
PE executable). This is what may cause an app to crash on the runtime
with an exception similar to:

    android.runtime.JavaProxyThrowable: System.NotSupportedException: Cannot create instance of type 'com.glmsoftware.OBDNowProto.SettingsFragmentCompat': no Java peer type found.
      at Java.Interop.JniPeerMembers+JniInstanceMethods..ctor (System.Type declaringType) [0x0004b] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructorsForType (System.Type declaringType) [0x00031] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.StartCreateInstance (System.String constructorSignature, System.Type declaringType, Java.Interop.JniArgumentValue* parameters) [0x00038] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at AndroidX.Preference.PreferenceFragmentCompat..ctor () [0x00034] in <005e3ae6340747e1aea6d08b095cf286>:0
      at com.glmsoftware.OBDNowProto.SettingsFragmentCompat..ctor () [0x00026] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at com.glmsoftware.OBDNowProto.SettingsActivity.OnCreate (Android.OS.Bundle bundle) [0x00083] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00011] in <c56099afccf04721853684f376a89527>:0
        at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.3(intptr,intptr,intptr)
        at crc64596a13587a898911.SettingsActivity.n_onCreate(Native Method)
        at crc64596a13587a898911.SettingsActivity.onCreate(SettingsActivity.java:40)
        at android.app.Activity.performCreate(Activity.java:7825)
        at android.app.Activity.performCreate(Activity.java:7814)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

Thus, we need to revert the Debug builds to the variation of the old
string-based type name mapping. This commit implements it in a slightly
leaner form than it was implemented before
ce2bc68 landed in that only one copy of
each set of type names (Java and managed) is maintained in both memory
and on disk, at a tiny (sub millisecond) expense at the run time to fix
up pointers between the two tables.
grendello added a commit to grendello/xamarin-android that referenced this issue Apr 1, 2020
Fixes: dotnet#4415
Context: dotnet@ce2bc68

This commit partially reverts ce2bc68
in the sense that it restores the use of type names for Java-to-Managed
and Managed-to-Java type lookups for **Debug** builds only.

The reason for the change is that in order for the MVID and type token
based lookups to work we need two things:

  - for the MVID to remain unchanged in each mapped assembly
  - for the type token to remain unchanged in each mapped assembly

However, in incremental builds neither of the above requirements is
met **unless** the application is fully rebuilt and, thus, the typemaps
are regenerated from scratch, which obviously doesn't sit well with the
incremental nature of incremental builds :)

With MVID/token id maps, every change to any source code that's built
into a mapped assembly, may cause the assembly to change its MVID and
renaming of any type, removing or adding a type, will rearrange the type
definition table in the resulting assembly, thus changing the type token
ids (which are basically offsets into the type definition table in the
PE executable). This is what may cause an app to crash on the runtime
with an exception similar to:

    android.runtime.JavaProxyThrowable: System.NotSupportedException: Cannot create instance of type 'com.glmsoftware.OBDNowProto.SettingsFragmentCompat': no Java peer type found.
      at Java.Interop.JniPeerMembers+JniInstanceMethods..ctor (System.Type declaringType) [0x0004b] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructorsForType (System.Type declaringType) [0x00031] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.StartCreateInstance (System.String constructorSignature, System.Type declaringType, Java.Interop.JniArgumentValue* parameters) [0x00038] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at AndroidX.Preference.PreferenceFragmentCompat..ctor () [0x00034] in <005e3ae6340747e1aea6d08b095cf286>:0
      at com.glmsoftware.OBDNowProto.SettingsFragmentCompat..ctor () [0x00026] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at com.glmsoftware.OBDNowProto.SettingsActivity.OnCreate (Android.OS.Bundle bundle) [0x00083] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00011] in <c56099afccf04721853684f376a89527>:0
        at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.3(intptr,intptr,intptr)
        at crc64596a13587a898911.SettingsActivity.n_onCreate(Native Method)
        at crc64596a13587a898911.SettingsActivity.onCreate(SettingsActivity.java:40)
        at android.app.Activity.performCreate(Activity.java:7825)
        at android.app.Activity.performCreate(Activity.java:7814)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

Thus, we need to revert the Debug builds to the variation of the old
string-based type name mapping. This commit implements it in a slightly
leaner form than it was implemented before
ce2bc68 landed in that only one copy of
each set of type names (Java and managed) is maintained in both memory
and on disk, at a tiny (sub millisecond) expense at the run time to fix
up pointers between the two tables.
grendello added a commit to grendello/xamarin-android that referenced this issue Apr 1, 2020
Fixes: dotnet#4415
Context: dotnet@ce2bc68

This commit partially reverts ce2bc68
in the sense that it restores the use of type names for Java-to-Managed
and Managed-to-Java type lookups for **Debug** builds only.

The reason for the change is that in order for the MVID and type token
based lookups to work we need two things:

  - for the MVID to remain unchanged in each mapped assembly
  - for the type token to remain unchanged in each mapped assembly

However, in incremental builds neither of the above requirements is
met **unless** the application is fully rebuilt and, thus, the typemaps
are regenerated from scratch, which obviously doesn't sit well with the
incremental nature of incremental builds :)

With MVID/token id maps, every change to any source code that's built
into a mapped assembly, may cause the assembly to change its MVID and
renaming of any type, removing or adding a type, will rearrange the type
definition table in the resulting assembly, thus changing the type token
ids (which are basically offsets into the type definition table in the
PE executable). This is what may cause an app to crash on the runtime
with an exception similar to:

    android.runtime.JavaProxyThrowable: System.NotSupportedException: Cannot create instance of type 'com.glmsoftware.OBDNowProto.SettingsFragmentCompat': no Java peer type found.
      at Java.Interop.JniPeerMembers+JniInstanceMethods..ctor (System.Type declaringType) [0x0004b] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructorsForType (System.Type declaringType) [0x00031] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.StartCreateInstance (System.String constructorSignature, System.Type declaringType, Java.Interop.JniArgumentValue* parameters) [0x00038] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at AndroidX.Preference.PreferenceFragmentCompat..ctor () [0x00034] in <005e3ae6340747e1aea6d08b095cf286>:0
      at com.glmsoftware.OBDNowProto.SettingsFragmentCompat..ctor () [0x00026] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at com.glmsoftware.OBDNowProto.SettingsActivity.OnCreate (Android.OS.Bundle bundle) [0x00083] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00011] in <c56099afccf04721853684f376a89527>:0
        at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.3(intptr,intptr,intptr)
        at crc64596a13587a898911.SettingsActivity.n_onCreate(Native Method)
        at crc64596a13587a898911.SettingsActivity.onCreate(SettingsActivity.java:40)
        at android.app.Activity.performCreate(Activity.java:7825)
        at android.app.Activity.performCreate(Activity.java:7814)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

Thus, we need to revert the Debug builds to the variation of the old
string-based type name mapping. This commit implements it in a slightly
leaner form than it was implemented before
ce2bc68 landed in that only one copy of
each set of type names (Java and managed) is maintained in both memory
and on disk, at a tiny (sub millisecond) expense at the run time to fix
up pointers between the two tables.
grendello added a commit to grendello/xamarin-android that referenced this issue Apr 1, 2020
Fixes: dotnet#4415
Context: dotnet@ce2bc68

This commit partially reverts ce2bc68
in the sense that it restores the use of type names for Java-to-Managed
and Managed-to-Java type lookups for **Debug** builds only.

The reason for the change is that in order for the MVID and type token
based lookups to work we need two things:

  - for the MVID to remain unchanged in each mapped assembly
  - for the type token to remain unchanged in each mapped assembly

However, in incremental builds neither of the above requirements is
met **unless** the application is fully rebuilt and, thus, the typemaps
are regenerated from scratch, which obviously doesn't sit well with the
incremental nature of incremental builds :)

With MVID/token id maps, every change to any source code that's built
into a mapped assembly, may cause the assembly to change its MVID and
renaming of any type, removing or adding a type, will rearrange the type
definition table in the resulting assembly, thus changing the type token
ids (which are basically offsets into the type definition table in the
PE executable). This is what may cause an app to crash on the runtime
with an exception similar to:

    android.runtime.JavaProxyThrowable: System.NotSupportedException: Cannot create instance of type 'com.glmsoftware.OBDNowProto.SettingsFragmentCompat': no Java peer type found.
      at Java.Interop.JniPeerMembers+JniInstanceMethods..ctor (System.Type declaringType) [0x0004b] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructorsForType (System.Type declaringType) [0x00031] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.StartCreateInstance (System.String constructorSignature, System.Type declaringType, Java.Interop.JniArgumentValue* parameters) [0x00038] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at AndroidX.Preference.PreferenceFragmentCompat..ctor () [0x00034] in <005e3ae6340747e1aea6d08b095cf286>:0
      at com.glmsoftware.OBDNowProto.SettingsFragmentCompat..ctor () [0x00026] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at com.glmsoftware.OBDNowProto.SettingsActivity.OnCreate (Android.OS.Bundle bundle) [0x00083] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00011] in <c56099afccf04721853684f376a89527>:0
        at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.3(intptr,intptr,intptr)
        at crc64596a13587a898911.SettingsActivity.n_onCreate(Native Method)
        at crc64596a13587a898911.SettingsActivity.onCreate(SettingsActivity.java:40)
        at android.app.Activity.performCreate(Activity.java:7825)
        at android.app.Activity.performCreate(Activity.java:7814)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

Thus, we need to revert the Debug builds to the variation of the old
string-based type name mapping. This commit implements it in a slightly
leaner form than it was implemented before
ce2bc68 landed in that only one copy of
each set of type names (Java and managed) is maintained in both memory
and on disk, at a tiny (sub millisecond) expense at the run time to fix
up pointers between the two tables.
grendello added a commit to grendello/xamarin-android that referenced this issue Apr 2, 2020
Fixes: dotnet#4415
Context: dotnet@ce2bc68

This commit partially reverts ce2bc68
in the sense that it restores the use of type names for Java-to-Managed
and Managed-to-Java type lookups for **Debug** builds only.

The reason for the change is that in order for the MVID and type token
based lookups to work we need two things:

  - for the MVID to remain unchanged in each mapped assembly
  - for the type token to remain unchanged in each mapped assembly

However, in incremental builds neither of the above requirements is
met **unless** the application is fully rebuilt and, thus, the typemaps
are regenerated from scratch, which obviously doesn't sit well with the
incremental nature of incremental builds :)

With MVID/token id maps, every change to any source code that's built
into a mapped assembly, may cause the assembly to change its MVID and
renaming of any type, removing or adding a type, will rearrange the type
definition table in the resulting assembly, thus changing the type token
ids (which are basically offsets into the type definition table in the
PE executable). This is what may cause an app to crash on the runtime
with an exception similar to:

    android.runtime.JavaProxyThrowable: System.NotSupportedException: Cannot create instance of type 'com.glmsoftware.OBDNowProto.SettingsFragmentCompat': no Java peer type found.
      at Java.Interop.JniPeerMembers+JniInstanceMethods..ctor (System.Type declaringType) [0x0004b] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructorsForType (System.Type declaringType) [0x00031] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.StartCreateInstance (System.String constructorSignature, System.Type declaringType, Java.Interop.JniArgumentValue* parameters) [0x00038] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at AndroidX.Preference.PreferenceFragmentCompat..ctor () [0x00034] in <005e3ae6340747e1aea6d08b095cf286>:0
      at com.glmsoftware.OBDNowProto.SettingsFragmentCompat..ctor () [0x00026] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at com.glmsoftware.OBDNowProto.SettingsActivity.OnCreate (Android.OS.Bundle bundle) [0x00083] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00011] in <c56099afccf04721853684f376a89527>:0
        at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.3(intptr,intptr,intptr)
        at crc64596a13587a898911.SettingsActivity.n_onCreate(Native Method)
        at crc64596a13587a898911.SettingsActivity.onCreate(SettingsActivity.java:40)
        at android.app.Activity.performCreate(Activity.java:7825)
        at android.app.Activity.performCreate(Activity.java:7814)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

Thus, we need to revert the Debug builds to the variation of the old
string-based type name mapping. This commit implements it in a slightly
leaner form than it was implemented before
ce2bc68 landed in that only one copy of
each set of type names (Java and managed) is maintained in both memory
and on disk, at a tiny (sub millisecond) expense at the run time to fix
up pointers between the two tables.
grendello added a commit to grendello/xamarin-android that referenced this issue Apr 3, 2020
Fixes: dotnet#4415
Context: dotnet@ce2bc68

This commit partially reverts ce2bc68
in the sense that it restores the use of type names for Java-to-Managed
and Managed-to-Java type lookups for **Debug** builds only.

The reason for the change is that in order for the MVID and type token
based lookups to work we need two things:

  - for the MVID to remain unchanged in each mapped assembly
  - for the type token to remain unchanged in each mapped assembly

However, in incremental builds neither of the above requirements is
met **unless** the application is fully rebuilt and, thus, the typemaps
are regenerated from scratch, which obviously doesn't sit well with the
incremental nature of incremental builds :)

With MVID/token id maps, every change to any source code that's built
into a mapped assembly, may cause the assembly to change its MVID and
renaming of any type, removing or adding a type, will rearrange the type
definition table in the resulting assembly, thus changing the type token
ids (which are basically offsets into the type definition table in the
PE executable). This is what may cause an app to crash on the runtime
with an exception similar to:

    android.runtime.JavaProxyThrowable: System.NotSupportedException: Cannot create instance of type 'com.glmsoftware.OBDNowProto.SettingsFragmentCompat': no Java peer type found.
      at Java.Interop.JniPeerMembers+JniInstanceMethods..ctor (System.Type declaringType) [0x0004b] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructorsForType (System.Type declaringType) [0x00031] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.StartCreateInstance (System.String constructorSignature, System.Type declaringType, Java.Interop.JniArgumentValue* parameters) [0x00038] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at AndroidX.Preference.PreferenceFragmentCompat..ctor () [0x00034] in <005e3ae6340747e1aea6d08b095cf286>:0
      at com.glmsoftware.OBDNowProto.SettingsFragmentCompat..ctor () [0x00026] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at com.glmsoftware.OBDNowProto.SettingsActivity.OnCreate (Android.OS.Bundle bundle) [0x00083] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00011] in <c56099afccf04721853684f376a89527>:0
        at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.3(intptr,intptr,intptr)
        at crc64596a13587a898911.SettingsActivity.n_onCreate(Native Method)
        at crc64596a13587a898911.SettingsActivity.onCreate(SettingsActivity.java:40)
        at android.app.Activity.performCreate(Activity.java:7825)
        at android.app.Activity.performCreate(Activity.java:7814)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

Thus, we need to revert the Debug builds to the variation of the old
string-based type name mapping. This commit implements it in a slightly
leaner form than it was implemented before
ce2bc68 landed in that only one copy of
each set of type names (Java and managed) is maintained in both memory
and on disk, at a tiny (sub millisecond) expense at the run time to fix
up pointers between the two tables.
grendello added a commit to grendello/xamarin-android that referenced this issue Apr 6, 2020
Fixes: dotnet#4415
Context: dotnet@ce2bc68

This commit partially reverts ce2bc68
in the sense that it restores the use of type names for Java-to-Managed
and Managed-to-Java type lookups for **Debug** builds only.

The reason for the change is that in order for the MVID and type token
based lookups to work we need two things:

  - for the MVID to remain unchanged in each mapped assembly
  - for the type token to remain unchanged in each mapped assembly

However, in incremental builds neither of the above requirements is
met **unless** the application is fully rebuilt and, thus, the typemaps
are regenerated from scratch, which obviously doesn't sit well with the
incremental nature of incremental builds :)

With MVID/token id maps, every change to any source code that's built
into a mapped assembly, may cause the assembly to change its MVID and
renaming of any type, removing or adding a type, will rearrange the type
definition table in the resulting assembly, thus changing the type token
ids (which are basically offsets into the type definition table in the
PE executable). This is what may cause an app to crash on the runtime
with an exception similar to:

    android.runtime.JavaProxyThrowable: System.NotSupportedException: Cannot create instance of type 'com.glmsoftware.OBDNowProto.SettingsFragmentCompat': no Java peer type found.
      at Java.Interop.JniPeerMembers+JniInstanceMethods..ctor (System.Type declaringType) [0x0004b] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructorsForType (System.Type declaringType) [0x00031] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.StartCreateInstance (System.String constructorSignature, System.Type declaringType, Java.Interop.JniArgumentValue* parameters) [0x00038] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at AndroidX.Preference.PreferenceFragmentCompat..ctor () [0x00034] in <005e3ae6340747e1aea6d08b095cf286>:0
      at com.glmsoftware.OBDNowProto.SettingsFragmentCompat..ctor () [0x00026] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at com.glmsoftware.OBDNowProto.SettingsActivity.OnCreate (Android.OS.Bundle bundle) [0x00083] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00011] in <c56099afccf04721853684f376a89527>:0
        at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.3(intptr,intptr,intptr)
        at crc64596a13587a898911.SettingsActivity.n_onCreate(Native Method)
        at crc64596a13587a898911.SettingsActivity.onCreate(SettingsActivity.java:40)
        at android.app.Activity.performCreate(Activity.java:7825)
        at android.app.Activity.performCreate(Activity.java:7814)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

Thus, we need to revert the Debug builds to the variation of the old
string-based type name mapping. This commit implements it in a slightly
leaner form than it was implemented before
ce2bc68 landed in that only one copy of
each set of type names (Java and managed) is maintained in both memory
and on disk, at a tiny (sub millisecond) expense at the run time to fix
up pointers between the two tables.
grendello added a commit to grendello/xamarin-android that referenced this issue Apr 6, 2020
Fixes: dotnet#4415
Context: dotnet@ce2bc68

This commit partially reverts ce2bc68
in the sense that it restores the use of type names for Java-to-Managed
and Managed-to-Java type lookups for **Debug** builds only.

The reason for the change is that in order for the MVID and type token
based lookups to work we need two things:

  - for the MVID to remain unchanged in each mapped assembly
  - for the type token to remain unchanged in each mapped assembly

However, in incremental builds neither of the above requirements is
met **unless** the application is fully rebuilt and, thus, the typemaps
are regenerated from scratch, which obviously doesn't sit well with the
incremental nature of incremental builds :)

With MVID/token id maps, every change to any source code that's built
into a mapped assembly, may cause the assembly to change its MVID and
renaming of any type, removing or adding a type, will rearrange the type
definition table in the resulting assembly, thus changing the type token
ids (which are basically offsets into the type definition table in the
PE executable). This is what may cause an app to crash on the runtime
with an exception similar to:

    android.runtime.JavaProxyThrowable: System.NotSupportedException: Cannot create instance of type 'com.glmsoftware.OBDNowProto.SettingsFragmentCompat': no Java peer type found.
      at Java.Interop.JniPeerMembers+JniInstanceMethods..ctor (System.Type declaringType) [0x0004b] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructorsForType (System.Type declaringType) [0x00031] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.StartCreateInstance (System.String constructorSignature, System.Type declaringType, Java.Interop.JniArgumentValue* parameters) [0x00038] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at AndroidX.Preference.PreferenceFragmentCompat..ctor () [0x00034] in <005e3ae6340747e1aea6d08b095cf286>:0
      at com.glmsoftware.OBDNowProto.SettingsFragmentCompat..ctor () [0x00026] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at com.glmsoftware.OBDNowProto.SettingsActivity.OnCreate (Android.OS.Bundle bundle) [0x00083] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00011] in <c56099afccf04721853684f376a89527>:0
        at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.3(intptr,intptr,intptr)
        at crc64596a13587a898911.SettingsActivity.n_onCreate(Native Method)
        at crc64596a13587a898911.SettingsActivity.onCreate(SettingsActivity.java:40)
        at android.app.Activity.performCreate(Activity.java:7825)
        at android.app.Activity.performCreate(Activity.java:7814)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

Thus, we need to revert the Debug builds to the variation of the old
string-based type name mapping. This commit implements it in a slightly
leaner form than it was implemented before
ce2bc68 landed in that only one copy of
each set of type names (Java and managed) is maintained in both memory
and on disk, at a tiny (sub millisecond) expense at the run time to fix
up pointers between the two tables.
grendello added a commit to grendello/xamarin-android that referenced this issue Apr 6, 2020
Fixes: dotnet#4415
Context: dotnet@ce2bc68

This commit partially reverts ce2bc68
in the sense that it restores the use of type names for Java-to-Managed
and Managed-to-Java type lookups for **Debug** builds only.

The reason for the change is that in order for the MVID and type token
based lookups to work we need two things:

  - for the MVID to remain unchanged in each mapped assembly
  - for the type token to remain unchanged in each mapped assembly

However, in incremental builds neither of the above requirements is
met **unless** the application is fully rebuilt and, thus, the typemaps
are regenerated from scratch, which obviously doesn't sit well with the
incremental nature of incremental builds :)

With MVID/token id maps, every change to any source code that's built
into a mapped assembly, may cause the assembly to change its MVID and
renaming of any type, removing or adding a type, will rearrange the type
definition table in the resulting assembly, thus changing the type token
ids (which are basically offsets into the type definition table in the
PE executable). This is what may cause an app to crash on the runtime
with an exception similar to:

    android.runtime.JavaProxyThrowable: System.NotSupportedException: Cannot create instance of type 'com.glmsoftware.OBDNowProto.SettingsFragmentCompat': no Java peer type found.
      at Java.Interop.JniPeerMembers+JniInstanceMethods..ctor (System.Type declaringType) [0x0004b] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructorsForType (System.Type declaringType) [0x00031] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at Java.Interop.JniPeerMembers+JniInstanceMethods.StartCreateInstance (System.String constructorSignature, System.Type declaringType, Java.Interop.JniArgumentValue* parameters) [0x00038] in <e3e4dfa992a7411b85acfe193481be3e>:0
      at AndroidX.Preference.PreferenceFragmentCompat..ctor () [0x00034] in <005e3ae6340747e1aea6d08b095cf286>:0
      at com.glmsoftware.OBDNowProto.SettingsFragmentCompat..ctor () [0x00026] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at com.glmsoftware.OBDNowProto.SettingsActivity.OnCreate (Android.OS.Bundle bundle) [0x00083] in <a8dbee4be1674aa08cce57b50f21e347>:0
      at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00011] in <c56099afccf04721853684f376a89527>:0
        at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.3(intptr,intptr,intptr)
        at crc64596a13587a898911.SettingsActivity.n_onCreate(Native Method)
        at crc64596a13587a898911.SettingsActivity.onCreate(SettingsActivity.java:40)
        at android.app.Activity.performCreate(Activity.java:7825)
        at android.app.Activity.performCreate(Activity.java:7814)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

Thus, we need to revert the Debug builds to the variation of the old
string-based type name mapping. This commit implements it in a slightly
leaner form than it was implemented before
ce2bc68 landed in that only one copy of
each set of type names (Java and managed) is maintained in both memory
and on disk, at a tiny (sub millisecond) expense at the run time to fix
up pointers between the two tables.
jonpryor pushed a commit that referenced this issue Apr 6, 2020
Fixes: #4415
Context: ce2bc68

Commit ce2bc68 optimized type mappings between managed types and Java
types in large part by removing strings from the managed -> JNI
mapping: instead of using an assembly-qualified *string* as a key,
the assembly MVID & type metadata token were used as keys.

This setup works reliably in Release apps, in which the assemblies
don't change.  In a commercial Debug with Fast Deployment situation,
it falls down badly because every change to any source code that's
built into a mapped assembly may cause the assembly to change its
MVID, and renaming of any type -- removing or adding a type -- will
rearrange the type definition table in the resulting assembly, thus
changing the type token ids (which are basically offsets into the
type definition table in the PE executable).  This is what may cause
an app to crash on the runtime with an exception similar to:

	android.runtime.JavaProxyThrowable: System.NotSupportedException: Cannot create instance of type 'com.glmsoftware.OBDNowProto.SettingsFragmentCompat': no Java peer type found.
	  at Java.Interop.JniPeerMembers+JniInstanceMethods..ctor (System.Type declaringType) [0x0004b] in <e3e4dfa992a7411b85acfe193481be3e>:0
	  at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructorsForType (System.Type declaringType) [0x00031] in <e3e4dfa992a7411b85acfe193481be3e>:0
	  at Java.Interop.JniPeerMembers+JniInstanceMethods.StartCreateInstance (System.String constructorSignature, System.Type declaringType, Java.Interop.JniArgumentValue* parameters) [0x00038] in <e3e4dfa992a7411b85acfe193481be3e>:0
	  at AndroidX.Preference.PreferenceFragmentCompat..ctor () [0x00034] in <005e3ae6340747e1aea6d08b095cf286>:0
	  at com.glmsoftware.OBDNowProto.SettingsFragmentCompat..ctor () [0x00026] in <a8dbee4be1674aa08cce57b50f21e347>:0
	  at com.glmsoftware.OBDNowProto.SettingsActivity.OnCreate (Android.OS.Bundle bundle) [0x00083] in <a8dbee4be1674aa08cce57b50f21e347>:0
	  at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00011] in <c56099afccf04721853684f376a89527>:0
	    at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.3(intptr,intptr,intptr)
	    at crc64596a13587a898911.SettingsActivity.n_onCreate(Native Method)
	    at crc64596a13587a898911.SettingsActivity.onCreate(SettingsActivity.java:40)
	    at android.app.Activity.performCreate(Activity.java:7825)
	    at android.app.Activity.performCreate(Activity.java:7814)
	    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
	    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
	    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
	    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
	    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
	    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
	    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
	    at android.os.Handler.dispatchMessage(Handler.java:107)
	    at android.os.Looper.loop(Looper.java:214)
	    at android.app.ActivityThread.main(ActivityThread.java:7356)
	    at java.lang.reflect.Method.invoke(Native Method)
	    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
	    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

A "workaround" would be fully rebuild the application, which negates
the point to incremental builds and the inner-dev-loop cycle.

The fix is to partially revert ce2bc68 in the sense that it restores
the use of string-based type names for Java-to-Managed and
Managed-to-Java type lookups for ***Debug*** builds only.  Unlike the
pre-ce2bc689 world, only *one* copy of the set of string names is
present within the data structures, at a tiny (sub millisecond) expense
at the run time to fix up pointers between the two tables.


~~ File Formats ~~

All data in all file formats remains little-endian.

In Debug configuration builds, each assembly will have a corresponding
`*.typemap` file which will be loaded at runtime.

The file format in pseudo-C++:

	struct DebugTypemapFileHeader {
	    byte                                magic [4];              // "XATS"
	    uint32_t                            format_version;         // 2
	    uint32_t                            entry_count;
	    uint32_t                            java_type_name_width;
	    uint32_t                            managed_type_name_width;
	    uint32_t                            assembly_name_size;
	    byte                                assembly_name [assembly_name_size];
	    DebugTypemapFileJavaToManagedEntry  java_to_managed [entry_count];
	    DebugTypemapFileManagedToJavaEntry  managed_to_java [entry_count];
	}

	struct DebugTypemapFileJavaToManagedEntry {
	    byte                jni_name [DebugTypemapFileHeader::java_type_name_width];
	    uint32_t            managed_index;  // Index into DebugTypemapFileHeader::managed_to_java
	};

	struct DebugTypemapFileManagedToJavaEntry {
	    byte                managed_name [DebugTypemapFileHeader::java_type_name_width];
	    uint32_t            jni_index;      // Index into DebugTypemapFileHeader::java_to_managed
	};

`DebugTypemapFileHeader::java_type_name_width` and
`DebugTypemapFileHeader::managed_type_name_width` are the maximum
length + 1 (terminating NUL) for JNI names and assembly-qualified
managed names.

`DebugTypemapFileJavaToManagedEntry::jni_name` and
`DebugTypemapFileManagedToJavaEntry::managed_name` are NUL-padded.
jonpryor pushed a commit that referenced this issue Apr 6, 2020
Fixes: #4415
Context: ce2bc68

Commit ce2bc68 optimized type mappings between managed types and Java
types in large part by removing strings from the managed -> JNI
mapping: instead of using an assembly-qualified *string* as a key,
the assembly MVID & type metadata token were used as keys.

This setup works reliably in Release apps, in which the assemblies
don't change.  In a commercial Debug with Fast Deployment situation,
it falls down badly because every change to any source code that's
built into a mapped assembly may cause the assembly to change its
MVID, and renaming of any type -- removing or adding a type -- will
rearrange the type definition table in the resulting assembly, thus
changing the type token ids (which are basically offsets into the
type definition table in the PE executable).  This is what may cause
an app to crash on the runtime with an exception similar to:

	android.runtime.JavaProxyThrowable: System.NotSupportedException: Cannot create instance of type 'com.glmsoftware.OBDNowProto.SettingsFragmentCompat': no Java peer type found.
	  at Java.Interop.JniPeerMembers+JniInstanceMethods..ctor (System.Type declaringType) [0x0004b] in <e3e4dfa992a7411b85acfe193481be3e>:0
	  at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructorsForType (System.Type declaringType) [0x00031] in <e3e4dfa992a7411b85acfe193481be3e>:0
	  at Java.Interop.JniPeerMembers+JniInstanceMethods.StartCreateInstance (System.String constructorSignature, System.Type declaringType, Java.Interop.JniArgumentValue* parameters) [0x00038] in <e3e4dfa992a7411b85acfe193481be3e>:0
	  at AndroidX.Preference.PreferenceFragmentCompat..ctor () [0x00034] in <005e3ae6340747e1aea6d08b095cf286>:0
	  at com.glmsoftware.OBDNowProto.SettingsFragmentCompat..ctor () [0x00026] in <a8dbee4be1674aa08cce57b50f21e347>:0
	  at com.glmsoftware.OBDNowProto.SettingsActivity.OnCreate (Android.OS.Bundle bundle) [0x00083] in <a8dbee4be1674aa08cce57b50f21e347>:0
	  at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00011] in <c56099afccf04721853684f376a89527>:0
	    at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.3(intptr,intptr,intptr)
	    at crc64596a13587a898911.SettingsActivity.n_onCreate(Native Method)
	    at crc64596a13587a898911.SettingsActivity.onCreate(SettingsActivity.java:40)
	    at android.app.Activity.performCreate(Activity.java:7825)
	    at android.app.Activity.performCreate(Activity.java:7814)
	    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
	    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
	    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
	    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
	    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
	    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
	    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
	    at android.os.Handler.dispatchMessage(Handler.java:107)
	    at android.os.Looper.loop(Looper.java:214)
	    at android.app.ActivityThread.main(ActivityThread.java:7356)
	    at java.lang.reflect.Method.invoke(Native Method)
	    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
	    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

A "workaround" would be fully rebuild the application, which negates
the point to incremental builds and the inner-dev-loop cycle.

The fix is to partially revert ce2bc68 in the sense that it restores
the use of string-based type names for Java-to-Managed and
Managed-to-Java type lookups for ***Debug*** builds only.  Unlike the
pre-ce2bc689 world, only *one* copy of the set of string names is
present within the data structures, at a tiny (sub millisecond) expense
at the run time to fix up pointers between the two tables.


~~ File Formats ~~

All data in all file formats remains little-endian.

In Debug configuration builds, each assembly will have a corresponding
`*.typemap` file which will be loaded at runtime.

The file format in pseudo-C++:

	struct DebugTypemapFileHeader {
	    byte                                magic [4];              // "XATS"
	    uint32_t                            format_version;         // 2
	    uint32_t                            entry_count;
	    uint32_t                            java_type_name_width;
	    uint32_t                            managed_type_name_width;
	    uint32_t                            assembly_name_size;
	    byte                                assembly_name [assembly_name_size];
	    DebugTypemapFileJavaToManagedEntry  java_to_managed [entry_count];
	    DebugTypemapFileManagedToJavaEntry  managed_to_java [entry_count];
	}

	struct DebugTypemapFileJavaToManagedEntry {
	    byte                jni_name [DebugTypemapFileHeader::java_type_name_width];
	    uint32_t            managed_index;  // Index into DebugTypemapFileHeader::managed_to_java
	};

	struct DebugTypemapFileManagedToJavaEntry {
	    byte                managed_name [DebugTypemapFileHeader::java_type_name_width];
	    uint32_t            jni_index;      // Index into DebugTypemapFileHeader::java_to_managed
	};

`DebugTypemapFileHeader::java_type_name_width` and
`DebugTypemapFileHeader::managed_type_name_width` are the maximum
length + 1 (terminating NUL) for JNI names and assembly-qualified
managed names.

`DebugTypemapFileJavaToManagedEntry::jni_name` and
`DebugTypemapFileManagedToJavaEntry::managed_name` are NUL-padded.
@brendanzagaeski
Copy link
Contributor

Release status update

A Preview version has now been published on Windows that includes the fix for this item.

The fix is not yet available on macOS. I will update this item again when a Preview version with the fix is available on macOS.

Fix included in Xamarin.Android 10.3.0.74

Fix included on Windows in Visual Studio 2019 version 16.6 Preview 3. To try the Preview version that includes the fix, check for the latest updates in Visual Studio Preview.

Fix not yet available on macOS.

@brendanzagaeski
Copy link
Contributor

Release status update

A Preview version of Xamarin.Android has now been published on macOS that includes the fix for this item.

Fix included in Xamarin.Android 10.3.0.74.

Fix included on macOS in Visual Studio 2019 for Mac version 8.6 Preview 2. To try the Preview version that includes the fix, check for the latest updates on the Preview updater channel.

@softlion
Copy link

I jut get this issue using the latest version of xamarin android, same reason: after incremental build.

@jonathanpeppers
Copy link
Member

@softlion can you file a new issue with updated MSBuild & android device logs?

This issue is so long ago, it is probably a completely different thing now.

@softlion
Copy link

I could, but it happened only once and cleared after rebuilding all / deleting the app. So can't repro !

@ghost ghost locked as resolved and limited conversation to collaborators Jun 4, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Area: App Runtime Issues in `libmonodroid.so`. regression
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants