【错误记录】NDK 报错 java.lang.UnsatisfiedLinkError 的一种处理方案 ( 主应用与依赖库 Module 的 CPU 架构配置不匹配导致 )(一)

简介: 【错误记录】NDK 报错 java.lang.UnsatisfiedLinkError 的一种处理方案 ( 主应用与依赖库 Module 的 CPU 架构配置不匹配导致 )(一)

文章目录

一、问题描述

二、问题排查

三、解决方案





一、问题描述


NDK 开发 , 在调用 JNI 对应 Java 类时 , 静态代码块中 System.loadLibrary 语句调用时 , 报如下错误 ;


 

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


2020-12-01 10:35:48.993 20837-20837/? E/AndroidRuntime: FATAL EXCEPTION: main

 

Process: kim.hsl.dex, PID: 20837
    java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/kim.hsl.dex-WPNFatgeDiPkh3jHexDmDg==/base.apk"],nativeLibraryDirectories=[/data/app/kim.hsl.dex-WPNFatgeDiPkh3jHexDmDg==/lib/arm64, /data/app/kim.hsl.dex-WPNFatgeDiPkh3jHexDmDg==/base.apk!/lib/arm64-v8a, /system/lib64, /hw_product/lib64, /system/product/lib64]]] couldn't find "libopenssl.so"
        at java.lang.Runtime.loadLibrary0(Runtime.java:1067)
        at java.lang.Runtime.loadLibrary0(Runtime.java:1007)
        at java.lang.System.loadLibrary(System.java:1668)
        at kim.hsl.multipledex.OpenSSL.<clinit>(OpenSSL.java:13)
        at kim.hsl.multipledex.OpenSSL.getBytes(OpenSSL.java:30)
        at kim.hsl.multipledex.ProxyApplication.attachBaseContext(ProxyApplication.java:124)
        at android.app.Application.attach(Application.java:358)
        at android.app.Instrumentation.newApplication(Instrumentation.java:1168)
        at android.app.LoadedApk.makeApplication(LoadedApk.java:1382)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7341)
        at android.app.ActivityThread.access$2400(ActivityThread.java:251)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2280)
        at android.os.Handler.dispatchMessage(Handler.java:110)
        at android.os.Looper.loop(Looper.java:219)
        at android.app.ActivityThread.main(ActivityThread.java:8375)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055)





二、问题排查


出现上述错误 , 就是 打包的 so 动态库没有找到 , 有很多问题都会导致该错误 , 如 build.gradle 中没有配置对应的 CPU 架构 , NDK 中调用的外部动态或静态依赖库的 CPU 架构不匹配 ;


这里我遇到的问题是 主应用 与 依赖库的 CPU 架构不匹配导致 ;


创建项目时选择如下选项 , 自动生成的 build.gradle 中默认生成 arm64-v8a, armeabi-v7a, x86, x86_64 四种 CPU 架构的动态库 , 这就比较坑 , 一般开发时只编译 armeabi-v7a 这一种 CPU 架构的动态库 ;

image.png



在主应用中 , 选择了 C++ 支持 , 系统自动生成的配置如下 :


plugins {
    id 'com.android.application'
    id 'kotlin-android'
}
android {
    compileSdkVersion 29
    buildToolsVersion "30.0.2"
    defaultConfig {
        applicationId "kim.hsl.myapplication"
        minSdkVersion 18
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags ""
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
}
dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.2'
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}



56


上述 android / defaultConfig / externalNativeBuild / cmake / abiFilters 配置中没有配置 CPU 架构 , 没有配置 abiFilters CPU 架构选项 , 因此默认生成 arm64-v8a, armeabi-v7a, x86, x86_64 四种 CPU 架构的动态库 ;


下图是主应用生成的 so 动态库 :




可以明显看到 主应用的依赖库生成了 四种 CPU 架构的动态库 , 我们使用的 libopenssl.so 动态库只有 armeabi-v7a 架构的 , 当在 arm64-v8a 架构的手机中调用 OpenSSL 所在的类时 , 在 static 静态代码块中的 System.loadLibrary 调用时就会报错 ;


该应用生成了 arm64-v8a 架构的动态库 , 但是生成的不全 , 导致上述问题 , 解决方案是干脆不生成 arm64-v8a 架构的动态库 , 只生成 armeabi-v7a 架构动态库 , arm64-v8a 架构的手机会向下兼容 armeabi-v7a 架构动态库 , 因此只编译生成 armeabi-v7a 架构动态库即可 ;



在另一个主应用的 Android Library 中 , 其也使用了 NDK , 并且使用了外部依赖库 OpenSSL 静态库 , 在 Ubuntu 中只交叉编译了 armeabi-v7a 架构的静态库 , 因此不能生成 arm64-v8a 的动态库 ;


下图是依赖库生成的 so 动态库 :


image.png


目前的主流手机都是 arm64-v8a 或 armeabi-v7a 手机 , x86 和 x86_64 手机很少 , 一般不进行匹配 ;


一般的高端机型都是 arm64-v8a 架构的 , 几年前的机型可能是 armeabi-v7a 架构的 ;


arm64-v8a 架构的手机 可以兼容使用 armeabi-v7a 架构的动态库 ;


不过要注意一点 , 前提是没有配置 arm64-v8a 架构 , 如果配置了 arm64-v8a 架构 , 但是没有对应 so 库 , 那就会出现上述错误 ;

image.png

目录
相关文章
|
1月前
|
消息中间件 Java Kafka
Java 事件驱动架构设计实战与 Kafka 生态系统组件实操全流程指南
本指南详解Java事件驱动架构与Kafka生态实操,涵盖环境搭建、事件模型定义、生产者与消费者实现、事件测试及高级特性,助你快速构建高可扩展分布式系统。
129 7
|
4月前
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
5月前
|
人工智能 安全 Java
智慧工地源码,Java语言开发,微服务架构,支持分布式和集群部署,多端覆盖
智慧工地是“互联网+建筑工地”的创新模式,基于物联网、移动互联网、BIM、大数据、人工智能等技术,实现对施工现场人员、设备、材料、安全等环节的智能化管理。其解决方案涵盖数据大屏、移动APP和PC管理端,采用高性能Java微服务架构,支持分布式与集群部署,结合Redis、消息队列等技术确保系统稳定高效。通过大数据驱动决策、物联网实时监测预警及AI智能视频监控,消除数据孤岛,提升项目可控性与安全性。智慧工地提供专家级远程管理服务,助力施工质量和安全管理升级,同时依托可扩展平台、多端应用和丰富设备接口,满足多样化需求,推动建筑行业数字化转型。
182 5
【YashanDB知识库】如何排查YMP报错:”OCI版本为空或OCI的架构和本地系统的架构不符“
【YashanDB知识库】如何排查YMP报错:”OCI版本为空或OCI的架构和本地系统的架构不符“
【YashanDB知识库】如何排查YMP报错:”OCI版本为空或OCI的架构和本地系统的架构不符“
|
2月前
|
缓存 Java 数据库
Java 项目分层架构实操指南及长尾关键词优化方案
本指南详解基于Spring Boot与Spring Cloud的Java微服务分层架构,以用户管理系统为例,涵盖技术选型、核心代码实现、服务治理及部署实践,助力掌握现代化Java企业级开发方案。
135 2
|
3月前
|
算法 架构师 Java
Java 开发岗及 java 架构师百度校招历年经典面试题汇总
以下是百度校招Java岗位面试题精选摘要(150字): Java开发岗重点关注集合类、并发和系统设计。HashMap线程安全可通过Collections.synchronizedMap()或ConcurrentHashMap实现,后者采用分段锁提升并发性能。负载均衡算法包括轮询、加权轮询和最少连接数,一致性哈希可均匀分布请求。Redis持久化有RDB(快照恢复快)和AOF(日志更安全)两种方式。架构师岗涉及JMM内存模型、happens-before原则和无锁数据结构(基于CAS)。
91 5
|
2月前
|
缓存 Cloud Native Java
Java 面试微服务架构与云原生技术实操内容及核心考点梳理 Java 面试
本内容涵盖Java面试核心技术实操,包括微服务架构(Spring Cloud Alibaba)、响应式编程(WebFlux)、容器化(Docker+K8s)、函数式编程、多级缓存、分库分表、链路追踪(Skywalking)等大厂高频考点,助你系统提升面试能力。
114 0
|
4月前
|
存储 监控 算法
Java程序员必学:JVM架构完全解读
Java 虚拟机(JVM)是 Java 编程的核心,深入理解其架构对开发者意义重大。本文详细解读 JVM 架构,涵盖类加载器子系统、运行时数据区等核心组件,剖析类加载机制,包括加载阶段、双亲委派模型等内容。阐述内存管理原理,介绍垃圾回收算法与常见回收器,并结合案例讲解调优策略。还分享 JVM 性能瓶颈识别与调优方法,分析 Java 语言特性对性能的影响,给出数据结构选择、I/O 操作及并发同步处理的优化技巧,同时探讨 JVM 安全模型与错误处理机制,助力开发者提升编程能力与程序性能。
Java程序员必学:JVM架构完全解读

热门文章

最新文章