Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

[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

未关闭
#13,263 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
5/5
预计耗时
一周以上
新手友好度
38/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
活跃
技术栈
android, csharp

调研方向

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.

由索引模型根据 Issue 内容生成。

描述

Area: App Runtime needs-triage
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;
}
  1. 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
主要语言
C#
星标
2.1k
派生
579
平均合并
1 天 9 小时
30 天内合并 PR
220

环境准备

  • 没有 Dockerfile 或 Docker Compose 文件
  • 有 Pull Request 模板
  • 没有贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

dotnet/android 的其他 Issue

查看 dotnet/android 的全部 Issue

相似的 Issue

更多 C# Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。