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

[net7] System.NotSupportedException: no Java peer type found #7736

Closed
jeromelaban opened this issue Jan 24, 2023 · 24 comments
Closed

[net7] System.NotSupportedException: no Java peer type found #7736

jeromelaban opened this issue Jan 24, 2023 · 24 comments
Assignees
Labels
Area: App+Library Build Issues when building Library projects or Application projects. needs-triage Issues that need to be assigned.

Comments

@jeromelaban
Copy link

jeromelaban commented Jan 24, 2023

Android application type

Android for .NET (net6.0-android, etc.)

Affected platform version

7.0.102

Description

After the fix in #7473, while the build now passes, I'm getting this runtime exception:

System.NotSupportedException: Cannot create instance of type 'Windows.UI.Xaml.NativeApplication+ActivityCallbacks': no Java peer type found.

Steps to Reproduce

  • dotnet new install Uno.ProjectTemplates.Dotnet
  • dotnet new unoapp -o testapp -f net7.0
  • cd testapp\testapp.Mobile
  • dotnet build -f net7.0-android -c Release

Did you find any workaround?

Setting the RuntimeIdentifier to a single architecture works around the issue:

<RuntimeIdentifier Condition="'$(TargetFramework)' == 'net7.0-android'">android-x64</RuntimeIdentifier>

But it is not a viable workaround as it does not allow for creating valid store packages.

Relevant log output

01-24 15:08:11.453 26988 26988 I MonoDroid: android.runtime.JavaProxyThrowable: System.NotSupportedException: Cannot create instance of type 'Windows.UI.Xaml.NativeApplication+ActivityCallbacks': no Java peer type found.
01-24 15:08:11.453 26988 26988 I MonoDroid:    at Java.Interop.JniPeerMembers.JniInstanceMethods..ctor(Type )
01-24 15:08:11.453 26988 26988 I MonoDroid:    at Java.Interop.JniPeerMembers.JniInstanceMethods.GetConstructorsForType(Type )
01-24 15:08:11.453 26988 26988 I MonoDroid:    at Java.Interop.JniPeerMembers.JniInstanceMethods.StartCreateInstance(String , Type , JniArgumentValue* )
01-24 15:08:11.453 26988 26988 I MonoDroid:    at Java.Lang.Object..ctor()
01-24 15:08:11.453 26988 26988 I MonoDroid:    at Windows.UI.Xaml.NativeApplication.ActivityCallbacks..ctor(NativeApplication )
01-24 15:08:11.453 26988 26988 I MonoDroid:    at Windows.UI.Xaml.NativeApplication.OnCreate()
01-24 15:08:11.453 26988 26988 I MonoDroid:    at Android.App.Application.n_OnCreate(IntPtr , IntPtr )
01-24 15:08:11.453 26988 26988 I MonoDroid:    at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PP_V(_JniMarshal_PP_V , IntPtr , IntPtr )
01-24 15:08:11.453 26988 26988 I MonoDroid:     at crc64122dcf5ad656876d.NativeApplication.n_onCreate(Native Method)
01-24 15:08:11.453 26988 26988 I MonoDroid:     at crc64122dcf5ad656876d.NativeApplication.onCreate(NativeApplication.java:26)
01-24 15:08:11.453 26988 26988 I MonoDroid:     at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1223)
01-24 15:08:11.453 26988 26988 I MonoDroid:     at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6766)
01-24 15:08:11.453 26988 26988 I MonoDroid:     at android.app.ActivityThread.access$1500(ActivityThread.java:256)
01-24 15:08:11.453 26988 26988 I MonoDroid:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2091)
01-24 15:08:11.453 26988 26988 I MonoDroid:     at android.os.Handler.dispatchMessage(Handler.java:106)
01-24 15:08:11.453 26988 26988 I MonoDroid:     at android.os.Looper.loopOnce(Looper.java:201)
01-24 15:08:11.453 26988 26988 I MonoDroid:     at android.os.Looper.loop(Looper.java:288)
01-24 15:08:11.453 26988 26988 I MonoDroid:     at android.app.ActivityThread.main(ActivityThread.java:7874)
01-24 15:08:11.453 26988 26988 I MonoDroid:     at java.lang.reflect.Method.invoke(Native Method)
01-24 15:08:11.453 26988 26988 I MonoDroid:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
01-24 15:08:11.453 26988 26988 I MonoDroid:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
01-24 15:08:11.453 26988 26988 I MonoDroid:
01-24 15:08:11.453 26988 26988 I MonoDroid:   --- End of managed Android.Runtime.JavaProxyThrowable stack trace ---
@jeromelaban
Copy link
Author

@jonathanpeppers I did not validate that at runtime #7473 would not cause issues, but it definitely does... It's a blocker, and if someone knows of a workaround, I'm interested :)

@grendello grendello added Area: App+Library Build Issues when building Library projects or Application projects. and removed Area: App Runtime Issues in `libmonodroid.so`. labels Jan 25, 2023
@jonathanpeppers
Copy link
Member

@jeromelaban have you looked into removing IsTrimmable from some of the Uno assemblies on Android? When I looked, I think this was triggering this issue.

@jeromelaban
Copy link
Author

@jonathanpeppers Thanks! I've tried adding a TrimmerRootDescriptor to exclude most assemblies (which is essentially the same as IsTrimmable metadata), but it does not seem to have an effect.

@jonathanpeppers
Copy link
Member

Can you share an example of how you set TrimmerRootDescriptor?

@jeromelaban
Copy link
Author

jeromelaban commented Jan 25, 2023

Sure, it's:

<ItemGroup>
	<TrimmerRootDescriptor Include="Android\LinkerConfig.xml" />
</ItemGroup>

then:

<?xml version="1.0" encoding="utf-8" ?>
<linker>
	<assembly fullname="Uno.UI"/>
	<assembly fullname="Uno"/>
	<assembly fullname="Uno.UI.Toolkit"/>
</linker>

The file is properly used during the build:

C:\Program Files\dotnet\dotnet.exe 
"C:\Program Files\dotnet\sdk\7.0.200-preview.22628.1\Sdks\Microsoft.NET.ILLink.Tasks\tools\net7.0\illink.dll"
 -x "Android\LinkerConfig.xml"

The assemblies really are not linked as all types are preserved, but maybe the linker still does some modifications that are impacting the android tooling?

@jonathanpeppers
Copy link
Member

I see potentially this many that would need to be in the list:

image

Let me play with it to get a workaround -- which might point to where the issue is.

@jeromelaban
Copy link
Author

Yes, many others could, though linking out Uno.UI is a canary for all the others (Windows.UI.Xaml.NativeApplication+ActivityCallbacks is in Uno.UI), as the error message stays the same indicating that it does not seem to have an effect.

@jonathanpeppers
Copy link
Member

Ok, I think I have narrowed it down to this line:

https://github.com/unoplatform/uno/blob/4be29fe5ea9249f60bd554148c169d583ccec58c/src/Uno.UI/UI/Xaml/SpecializedResourceDictionary.cs#L120

The linker is inlining IntPtr.Size:

image

And so you get a different Uno.UI.dll for android-arm vs android-arm64. Which results in an app that has:

assemblies/AllTheOtherOnes.dll
assemblies/armeabi-v7a/Uno.UI.dll
assemblies/arm64-v8a/Uno.UI.dll

I suspect a workaround might be to only target 64-bit via: RuntimeIdentifers=android-arm64;android-x64

I will play with linker settings and see if I can get it to not inline IntPtr.Size like this.

We also should look into the actual bug here, it seems like we could replicate this issue in a smaller test case.

@jeromelaban
Copy link
Author

Thanks for the detailed analysis! I can confirm that RuntimeIdentifers=android-arm64;android-x64 indeed produces a valid package!

@dellis1972
Copy link
Contributor

I think we have seen this kind of issue before where using IntPtr.Size results in different assemblies.
I wonder if there is a way to detect the issue and warn about it?

@jonathanpeppers
Copy link
Member

Trying to repro it here: main...jonathanpeppers:ArchitectureSpecificActivity

I should be able to get further tomorrow. I think you need a Java.Lang.Object subclass in an assembly with IsTrimmable=true that also uses IntPtr.Size.

@jonathanpeppers
Copy link
Member

My simple repro works... Doing Console.WriteLine(IntPtr.Size) in an activity in a trimmable class library appears to not cause an issue:

arm:

image

arm64:

image

Next steps, I need to look at the Uno app more and see why it causes this.

@dellis1972
Copy link
Contributor

I seem to remember a library which have a #if for different 32 vs 64 bit behaviour. Not sure if that was Uno or not...

@dellis1972
Copy link
Contributor

@jonathanpeppers yes it was uno its that #if TARGET64 code in the link you posted. You need to have the #if in there.

@jeromelaban
Copy link
Author

This particular code in Uno is an extract of the Dictionary class, but we cannot have bitness variations at compile time like the runtime is able to do. Now, I could try working around this issue by using Marshal.SizeOf, which may be able to give the same results, without the intrinsics kicking in.

@jonathanpeppers
Copy link
Member

I think it just defines TARGET_64BIT at the top of this file:

https://github.com/unoplatform/uno/blob/bd2789df8f9a2014dacff88751dfe20117b5fa6b/src/Uno.UI/UI/Xaml/SpecializedResourceDictionary.cs#L5

I don't think TARGET_64BIT is a thing the .NET SDK adds automatically.

@jeromelaban
Copy link
Author

Indeed, it's forcefully defined at the top, the idea was to not diverge too much from the original implementation and use a runtime check to enable 64bits code paths.

@jonathanpeppers
Copy link
Member

Marshal.SizeOf() (or some other API) probably would also work around the problem, they have the rule for inlining IntPtr.Size here:

https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.64bit.xml

@jeromelaban
Copy link
Author

jeromelaban commented Jan 26, 2023

Good news, avoiding IntPtr.Size does fix the issue, presumably because the assemblies can now actually be shared across architectures. Thanks for the hints @dellis1972 @jonathanpeppers, it was very useful!!

@jonathanpeppers
Copy link
Member

Great! I would still like to figure out what is going wrong here...

It seems like there is a problem with typemaps and assemblies that are architecture-specific, but they seem to work fine in the simple case.

@jonathanpeppers
Copy link
Member

I went further this morning, and tried two tests cases based on our .NET 7 branch:

release/7.0.1xx...jonathanpeppers:Test7736

These still pass. So, I think we are back to inspecting the Uno template and see why it's going wrong there.

@DevronB
Copy link

DevronB commented Jan 27, 2023

Thanks for the detailed analysis! I can confirm that RuntimeIdentifers=android-arm64;android-x64 indeed produces a valid package!

For what it's worth I have tried this for my issue here: dotnet/android-libraries#686 (comment) and I no longer have the Mapsui crash. I don't use the UNO libraries.

@jonathanpeppers @jeromelaban

@DevronB
Copy link

DevronB commented Jan 30, 2023

hmmm, it seems to be ok now...

I ran a dotnet workload install maui and deleted obj and bin folders and rebuilt the release build. Not sure which had an effect.

@jonpryor
Copy link
Member

This should be fixed via 929e701 (main), c5a84b8 (net7), and the most recent comment.

Closing.

@github-actions github-actions bot locked and limited conversation to collaborators Jan 23, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Area: App+Library Build Issues when building Library projects or Application projects. needs-triage Issues that need to be assigned.
Projects
None yet
Development

No branches or pull requests

6 participants