[CoreCLR] A library in `AndroidNativeLibraryNoJniPreload` is loaded with `System.loadLibrary` from the main thread on its first p/invoke, which fails 4 times in the system namespace before the call binds
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Aptitud para principiantes
- 38/100
- Tipo de issue
- Error
- Claridad
- Bastante claro
- Estado de actividad
- Activo
- Stack tecnológico
- android, csharp
- Área
- backend-api-design, mobile
Línea de trabajo
Start by tracing CoreCLR’s Android P/Invoke library-loading path, especially the MainThreadDsoLoader and SystemLoadLibraryWrapper::load entry points identified in the report. Reproduce with the supplied AndroidNativeLibraryNoJniPreload project on Android arm64 and inspect the first repro_add call and its log output. Done means the already loaded app library binds without failed system-namespace loads or repeated delays.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Android framework version
net11.0-android (Preview)
Affected platform version
.NET SDK 11.0.100-rc.2.26504.105, Android workload 37.2.0-rc.2.84, CoreCLR (UseMonoRuntime=false), Release, android-arm64; Android 17 (API 37) emulator
Description
On CoreCLR, an app's own native library that is listed in AndroidNativeLibraryNoJniPreload is not found by the first [DllImport] into it. Before the call binds, the runtime posts a load of the library to the main thread, which calls java.lang.System.loadLibrary. There the caller is the framework (caller=/system/framework/framework.jar), so the library is looked for in the system linker namespace, not the app's class-loader namespace, and it fails 4 times. Each failure is logged with its stack. Then monodroid-assembly warns "Shared library '...' not loaded, p/invoke '...' may fail", and the call is bound some other way and works.
This happens whether or not the app has already loaded the library itself with System.loadLibrary from its activity, which is what such an app does.
Why we list a library there: Firebase's C++ library (libFirebaseCppApp) reads the activity in its JNI_OnLoad, so it must not be preloaded as the process starts. The app loads it from its activity instead. With its ~37 p/invokes, an app gets ~150 UnsatisfiedLinkError stacks (half its logcat) and the main thread is held at every first call.
Cost in the repro below: the first call takes 528-896 ms, against 0.9 ms when the library is preloaded.
Expected
The first repro_add call binds to the app's lib/arm64/libreprolib.so (already loaded in the java_first true case) with no failed loads, as when the library is preloaded (-p:ReproPreload=true: 0 failures, first call 0.9 ms).
Notes
From the runtime's own strings (libnet-android.release.so: MainThreadDsoLoader, "Looper CB called on thread %d. Will attempt to load DSO", SystemLoadLibraryWrapper::load), the lookup goes through a load posted to the main thread's looper. Called from a looper callback, System.loadLibrary has no app frame on the stack, so the library is resolved in the system namespace, where an app's library is never found. Calling Runtime.loadLibrary0 with the app's class loader (or dlopen of the library's path in the app's native library directory) would find it. The lookup also doesn't notice that the app has already loaded the library. Because the warning path returns no handle, every first call of each import pays again.
Steps to Reproduce
#include <jni.h>
#include <android/log.h>
int repro_add(int a, int b) { return a + b; }
JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
__android_log_print(ANDROID_LOG_INFO, "Repro", "libreprolib JNI_OnLoad");
return JNI_VERSION_1_6;
}
dotnet new android, with this project file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net11.0-android</TargetFramework>
<SupportedOSPlatformVersion>24</SupportedOSPlatformVersion>
<OutputType>Exe</OutputType>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<ApplicationId>com.example.nojnipreloadrepro</ApplicationId>
<ApplicationVersion>1</ApplicationVersion>
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
<UseMonoRuntime>false</UseMonoRuntime>
<RuntimeIdentifiers>android-arm64</RuntimeIdentifiers>
</PropertyGroup>
<ItemGroup>
<AndroidNativeLibrary Include="../native/arm64-v8a/libreprolib.so" Abi="arm64-v8a" />
<AndroidNativeLibraryNoJniPreload Include="libreprolib.so" Condition="'$(ReproPreload)' != 'true'" />
</ItemGroup>
</Project>
and this activity:
using System.Runtime.InteropServices;
using Android.Util;
namespace NoJniPreloadRepro;
[Activity(Label = "@string/app_name", MainLauncher = true)]
public class MainActivity : Activity
{
[DllImport("reprolib")]
private static extern int repro_add(int a, int b);
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_main);
// --ez java_first true: the app loads the library itself first, as one whose JNI_OnLoad needs the activity does.
if (Intent?.GetBooleanExtra("java_first", false) == true)
{
Java.Lang.JavaSystem.LoadLibrary("reprolib");
Log.Info("Repro", "loaded libreprolib through Java (System.loadLibrary)");
}
// The first p/invoke, from a thread of the app's own.
new Thread(() =>
{
var watch = System.Diagnostics.Stopwatch.StartNew();
var sum = repro_add(2, 3);
Log.Info("Repro", $"repro_add(2, 3) = {sum}, first call took {watch.Elapsed.TotalMilliseconds:0.0} ms");
}).Start();
}
}
Did you find any workaround?
No response
Relevant log output
D nativeloader: Load libreprolib.so using system ns (caller=/system/framework/framework.jar!classes3.dex): dlopen failed: library "libreprolib.so" not found
W System.err: java.lang.UnsatisfiedLinkError: dlopen failed: library "libreprolib.so" not found
W System.err: at java.lang.Runtime.loadLibrary0(Runtime.java:1122)
W System.err: at java.lang.Runtime.loadLibrary0(Runtime.java:1033)
W System.err: at java.lang.System.loadLibrary(System.java:1765)
W System.err: at android.os.MessageQueue.nativePollOnce(Native Method)
W System.err: at android.os.MessageQueue.next(MessageQueue.java:773)
W System.err: at android.os.Looper.loop(Looper.java:397)
W System.err: at android.app.ActivityThread.main(ActivityThread.java:9523)
... (4 times, on the main thread)
W monodroid-assembly: Shared library 'reprolib' not loaded, p/invoke 'repro_add' may fail (on the calling thread)
I Repro : repro_add(2, 3) = 5, first call took 895.6 ms
- Lenguaje dominante
- C#
- Estrellas
- 2.1k
- Forks
- 579
- Merge medio
- 1 d 16 h
- PR fusionados (30 d)
- 249
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Sin guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de dotnet/android
-
Area: App+Library Build
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Los mantenedores suelen responder en 1 día
-
EditText.getText() isn't boundAbiertoArea: Mono.Android
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
dotnet/android#9192 · 4 comentarios · 1 reacción ·
Los mantenedores suelen responder en 1 día
-
agentic-workflows needs-triage
Dificultad 4/5 1-2 días Aptitud para principiantes 25/100
Los mantenedores suelen responder en 1 día
-
[.NET 10 / .NET 11 RC2] Native JNI control blocks leak after peer finalizationPosiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. AbiertoArea: App Runtime needs-triage
Dificultad 4/5 3-5 días Aptitud para principiantes 35/100
Los mantenedores suelen responder en 1 día
-
AndroidTypeMapImplementation trimmable removes types that are used in type castsPosiblemente ocupada @simonrozsival la tomó hace 1 día. AbiertoArea: App Runtime bug trimmable-type-map
dotnet/android#13286 · 2 comentarios · 1 asignado ·
Los mantenedores suelen responder en 1 día
Todos los issues de dotnet/android
Issues similares
-
[Bug] Dashboard renders attachment links that resolve to 404 when the FILES binding is absentAbiertobug 優先: 低
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
Los mantenedores suelen responder en 1 día
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 92/100
-
.NET area: storage bug good first issue
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
Larson-Logan/medal-sync#61 ·
Los mantenedores suelen responder en 1 día
-
area-ai bug untriaged
Dificultad 2/5 1-3 horas Aptitud para principiantes 67/100
dotnet/extensions#7893 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 72/100