Java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader 翻译为:Java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader。

75

有没有人遇到过这个错误并且能提供经验?

java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/org.swig.simple-2/base.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]] couldn't find "liborg.swig.simple.example.so"

我用这种方式加载库时出现了错误。

static {
    System.loadLibrary("example");
}

我相信'example'类存在于当前文件夹中。

1
我测试了所有15个答案,但我的问题没有解决。我该怎么办? at java.lang.Runtime.loadLibrary(Runtime.java:367)``` - Sana Ebadi
21个回答

62
我目前正在开发一款流媒体广播的安卓应用程序。我使用了一个名为aacdecoder的本地解码器库。一切都很好,直到程序在一些安卓设备上崩溃报错。这真的很烦人,因为应用程序几乎可以在所有设备上完美地播放广播流,但是不能在三星S6和S6 Edge上播放。
崩溃报告显示:
Fatal Exception: java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file “/data/app/com.radyoland.android-1/base.apk”],nativeLibraryDirectories=[/data/app/com.radyoland.android-1/lib/arm64, /vendor/lib64, /system/lib64]]] couldn’t find “libaacdecoder.so”
 at java.lang.Runtime.loadLibrary(Runtime.java:366)
 at java.lang.System.loadLibrary(System.java:988)
 at com.spoledge.aacdecoder.Decoder.loadLibrary(Decoder.java:187)

你看到这个崩溃报告说它无法加载本地库。但是原因是什么呢?首先我检查了我的结构,如果本地库.so文件被正确地放置。

似乎除了这个疯狂的错误以外一切都没问题。然后经过一些研究,我发现一些Android设备有64位处理器。这些设备会生成并检查arm64文件夹来加载本地库。这就是问题所在。因为我的项目没有arm64文件夹。以下是解决方案;

defaultConfig {
    ...

    ndk {
        abiFilters "armeabi-v7a", "x86", "armeabi", "mips"
    }

}

你需要将这些过滤器(abiFilters)添加到您的应用程序模块的build.gradle文件中。因此,当您的设备尝试运行您的应用程序时,它将检查gradle文件并了解它不应生成任何文件夹并使用现有的本地库资源。嘭,问题基本上已经解决。但还有一件事情。
android.useDeprecatedNdk=true

将以下代码添加到gradle.properties中以使用已弃用的Ndk。

最终我的应用程序可以在S6和S6 Edge上运行。我是指它可以在任何拥有新的64位处理器的设备上运行。

更新:

截至2019年12月,armabi和mips已被弃用。支持的ABI为[arm64-v8a,armeabi-v7a,x86,x86_64]

因此,您的代码应该像这样:

defaultConfig {
        ...

        ndk {
            abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64"
        }

    }

1
谢谢!这是唯一可行的解决方案。 - Leonardo Assunção
1
android.useDeprecatedNdk=true 这个标志已经过时了。 - Muhammad Noman
2
截至2019年12月,armabi和mips已被弃用。支持的ABIs为[arm64-v8a,armeabi-v7a,x86,x86_64]。 - Aman
@RuberandindaPatience - tomeda
@RuberandindaPatience 感谢您的回复。但这是否意味着,如果我构建appgradle,它不会生成64位版本?Google Play商店要求所有应用都必须有64位版本。 - tomeda
显示剩余5条评论

55
请注意命名规范。您的库必须被称为libexample.so。
LoadLibrary("example")将查找libexample.so库。
.so库需要位于apk文件夹下的lib文件夹中(由于您正在开发Android应用,因此它需要位于lib / armeabi和lib / armeabi-v7a文件夹下——为什么这两个文件夹都要有?一些Android版本会在lib / armeabi下查找,另一些则会在lib / armeabi-v7a下查找...请查看哪种方法适合您)。
其他需要注意的事项:
- 确保编译正确的架构(如果编译为armebi v5,它将无法在armebiv7或armebiv7s上运行)。 - 确保在正确的类中使用导出的原型(检查hello jni示例。您公开的函数需要类似于Java_mypackagename_myjavabridgeclass_myfunction)。
例如,函数Java_com_example_sample_hello将在java类com.example.sample中翻译为hello函数。

我下载了这个例子 http://www.swig.org/Doc2.0/Android.html#Android_examples_intro 我的 CBU/ABI 是 armeabi-v7a有没有什么解决方案? - developergg
1
如果你是 JNI 新手,可以使用谷歌的示例:https://code.google.com/p/awesomeguy/wiki/JNITutorial。我个人不喜欢 Swig,尽量避免使用它。Swig 会给你的代码增加额外的复杂度,而且由于你还没有完全掌握 JNI 的概念,最好一开始就避免使用它(Swig 会为你生成一些东西...在你完全了解这些东西以及它们的用法之前,你无法充分地从 Swig 提供的功能中受益 ;))。 - MichaelCMS
我没有选择。因为我的客户给了我一个C++函数,我必须从我的Java代码中调用它。 - developergg
1
我只是在提示从哪里开始理解jni。我不能盲目地为您的上下文提供解决方案 :)。 - MichaelCMS
救了我,为那些事情苦苦挣扎了一天,我只有 armeabiv7 的版本,而没有 armeabi-v7a 的版本。 - Vikas Pandey
我和@developergg有同样的问题,但只在安卓7和8的Sony手机上出现。我的abifilters如下:"armeabi-v7a","arm64-v8a"。在其他设备上运行正常。有什么想法吗? - ilyamuromets

40

这对我很有帮助,分享给可能遇到同样问题的人。

android {
    ....
    defaultConfig {
        ....
        ndk {
            abiFilters "armeabi", "armeabi-v7a", "x86", "mips"
        }
    }
}

7
这并不解释为什么它对你有帮助。我也遇到了这个问题,已经设置好了abiFilters。 - IgorGanapolsky
谢谢,我只有“armeabi”的库,所以一直在想为什么我的armeabi-v7a库中的libc++_shared.so无法找到!哇,没有你的提示,我不知道怎么能够自己发现这个问题。 - TastyCatFood
这对我有所帮助,但我仍然不知道它为什么起作用。不过,谢谢! - Marty Miller
谢谢,兄弟,你救了我的一天。 - P A Gosai

13
我的解决方法是将jniLibs文件夹放在“main”文件夹下面,就在“java”和“res”文件夹旁边。例如:项目 -> 应用程序 -> src -> main -> jniLibs。
我已经按照正确的名称将所有库都放置在各自的架构子文件夹中,但仍然出现了相同的异常。我甚至尝试了很多其他堆栈溢出网站答案,如此处的已接受答案,编译一个包含.so库的JAR文件,尝试其他方式将jniLibs文件夹放置等等。
对于这个项目,我必须在Android Studio 1.5.1上使用Gradle 2.2和Android Plugin 1.1.0。

9

-如果gradle.properties文件不存在,则需要先创建该文件,并添加以下内容:android.useDeprecatedNdk=true

-在build.gradle中使用以下代码:

defaultConfig {
    applicationId 'com.example.application'
    minSdkVersion 16
    targetSdkVersion 21
    versionCode 11
    versionName "1.1"
    ndk {
        abiFilters "armeabi"
    }
}

`


8
我使用的是Android Studio 3.0,遇到了这个问题。我确定应用程序的build.gradle没有问题。
转到运行 -> 编辑配置 -> 分析,并禁用“启用高级分析”。
这对我有用。 参考答案

但为什么呢? - miracle-doh
非常感谢您。我已经启用了高级分析以调试网络流量,但第二天我遇到了这个错误,不知道为什么。 - Warpzit

7

我的建议是在build.gradle文件中注册jni文件的源目录。 将以下内容添加到您的gradle文件中:

android {
    sourceSets {
        main {
            jniLibs.srcDir '[YOUR_JNI_DIR]' // i.e. 'libs'
        }
    }
}

这对我来说是工作!在我的情况下,我指向包含*.so文件的libs目录。 - linjiejun

7

这是对我有用的。

如果你在 armeabi 文件夹中有 .so 文件,则只需在 ndk 中提及该文件夹。

defaultConfig {
        applicationId "com.xxx.yyy"
        minSdkVersion 17
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        renderscriptTargetApi 26
        renderscriptSupportModeEnabled true
        ndk {
            abiFilters "armeabi"
        }
    }

然后使用这个

android.useDeprecatedNdk=true;

在gradle.properties文件中。

在项目中找不到abiFilters()方法,参数[armeabi]无效。 - Roman Soviak
这对我有用如果您在armeabi中有.so文件,则在ndk中仅提到该文件夹。defaultConfig { applicationId "com.xxx.yyy" minSdkVersion 17 targetSdkVersion 26 versionCode 1 versionName "1.0" renderscriptTargetApi 26 renderscriptSupportModeEnabled true ndk { abiFilters "armeabi" } }然后使用此代码android.useDeprecatedNdk=true; 只需使用android.useDeprecatedNdk=true,不要加逗号。 - Emmanuel Njorodongo

5
如果您正在使用Android Studio,只需编辑根文件夹中的gradle.properties,并添加android.useDeprecatedNdk=true。然后编辑应用程序文件夹中的build.gradle文件,将abiFilters设置如下:
android {
....
defaultConfig {
    ....
    ndk {
        abiFilters "armeabi", "armeabi-v7a", "x86", "mips"
    }
}
}

5

一些旧的gradle工具无法将.so文件复制到构建文件夹中,手动将这些文件复制到构建文件夹中可以解决问题:

build/intermediates/rs/{build config}/{support architecture}/

构建配置:测试版/生产版/预发布版/用户验收测试版

支持架构:armeabi/armeabi-v7a/mips/x86


1
奇怪,也许这是一个Android Studio的bug?jniLibs文件夹也是一样。 - IgorGanapolsky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接