Android 源码中jni项目 加载so目录小结

2024-09-07 04:28

本文主要是介绍Android 源码中jni项目 加载so目录小结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Android 源码中jni项目 加载so目录小结

文章目录

  • Android 源码中jni项目 加载so目录小结
    • 一、前言
    • 二、so目录验证测试
      • 1、jni so文件错误报错
        • (1)报错1 - 未找到so文件:
        • (2)报错2 - so文件中未找到native方法:
      • 2、验证的几种情况
        • (1)apk下面的 lib/arm64/ 放置正确的so文件
        • (2)apk下面的 lib/arm64/ 放置错误的so文件
        • 所以上面两个测试,验证了 lib/arm64/ 目录才是首先选择的目录。
        • (3)apk下面的 lib/arm64/ 不放置so文件
          • ① system/lib 、vendor/lib64 、vendor/lib放置正确的so文件
        • 测试验证了,system/lib 、vendor/lib64 、vendor/lib 系统不会读取里面的so。
          • ② system/lib64 放置正确的so文件
          • ③system/lib64 放置错误的so文件
        • 测试验证了,系统应用会读取 system/lib64/ 下面的so。
    • 三、其他
      • 1、系统源码中加载so的具体实现
      • 2、Android JNI SO库和对应的CPU架构详解
      • 3、Android 系统源码项目加载预编好的so库

一、前言

如何实现把so放到Android设备目录system/lib64下面,系统应用apk就能自动获取里面的so?

如果实现了这个功能,后续修改了jni具体功能实现,

就不用修改这个apk的代码,只要替换这个so就可以完成不同的实现了。

其实这个功能不难,只要是系统源码编译的应用就可以;

具体如何编译可以看本文最后的介绍。

本文主要介绍一下,系统源码应用编译后,load so的顺序:

顺序就是优先apk目录下的 lib/arm64/,然后 system/lib64/,有的还会加载 vendor/lib64/

具体实现是cpp底层的,这里不做具体分析。

二、so目录验证测试

jni加载so代码:

static {System.loadLibrary("native-lib");
}

这里是没有写so路径的,so的固定命名规则是前面加 lib 后面加.so,所以正确的搜命名是:libnative-lib.so

这里拿一个其他错误的libnative-lib.so和一个正确的libnative-lib.so验证测试。

目录分别测试:apk下面的lib/arm64/,system/lib, system/lib64, vendor/lib64,vendor/lib

应用运行后保存主要有两种,一个是找不到so,一个是so找不到jni的方法。

1、jni so文件错误报错

(1)报错1 - 未找到so文件:
2024-09-04 16:10:42.987 1593-1593/? E/AndroidRuntime: FATAL EXCEPTION: mainProcess: com.demo.jnicallback, PID: 1593java.lang.UnsatisfiedLinkError: dlopen failed: library "libnative-lib.so" not foundat java.lang.Runtime.loadLibrary0(Runtime.java:1077)at java.lang.Runtime.loadLibrary0(Runtime.java:998)at java.lang.System.loadLibrary(System.java:1661)at com.liwenzhi.jnidemo.JniClass.<clinit>(JniClass.java:16)at com.demo.jnicallback.MainActivity.onCreate(MainActivity.java:27)

上面那几个目录下都没有so文件就会报这个错误。

(2)报错2 - so文件中未找到native方法:
    --------- beginning of crash
2024-09-04 15:32:04.294 1600-1600/? E/AndroidRuntime: FATAL EXCEPTION: mainProcess: com.demo.jnicallback, PID: 1600java.lang.UnsatisfiedLinkError: No implementation found for java.lang.String com.liwenzhi.jnidemo.JniClass.stringFromJNI() (tried Java_com_liwenzhi_jnidemo_JniClass_stringFromJNI and Java_com_liwenzhi_jnidemo_JniClass_stringFromJNI__)at com.liwenzhi.jnidemo.JniClass.stringFromJNI(Native Method)at com.demo.jnicallback.MainActivity.onCreate(MainActivity.java:28)

有so但是so里面的实现方法,包名不正常或者不存在这个 native方法就会报上面这个错误。

2、验证的几种情况

(1)apk下面的 lib/arm64/ 放置正确的so文件

其他目录不管放置错误的so文件还是不放置so文件都是不会报错的;

(2)apk下面的 lib/arm64/ 放置错误的so文件

其他目录不管放置正确的so文件还是不放置so文件都是会报错native方法不一致;

所以上面两个测试,验证了 lib/arm64/ 目录才是首先选择的目录。
(3)apk下面的 lib/arm64/ 不放置so文件
① system/lib 、vendor/lib64 、vendor/lib放置正确的so文件

运行后都是报错未找到so文件错误

测试验证了,system/lib 、vendor/lib64 、vendor/lib 系统不会读取里面的so。

其实这个情况不是绝对的,后面简单说一下,这个和应用的32位、64位有关,但是现在应用基本都是64位的了。

② system/lib64 放置正确的so文件

应用不会报错;

③system/lib64 放置错误的so文件

应用会报错native方法不一致;

测试验证了,系统应用会读取 system/lib64/ 下面的so。

上面几个测试,就验证了 so加载的顺序优先apk目录下的 lib/arm64/,然后 system/lib64/。

其实知道就行了,没啥太大必要进行验证测试。

三、其他

1、系统源码中加载so的具体实现

安卓so加载流程源码分析

https://oacia.dev/android-load-so/

android so的加载流程(Android 13~14)

https://blog.csdn.net/qq_61253776/article/details/141675312

在系统中确实看到有应用是加载到了 vendor/lib64 下面的so,

但是不知道为啥我编的系统应用无法加载到这个目录下面的so,这个有待研究!

2、Android JNI SO库和对应的CPU架构详解

armeabi:第五代、第六代ARM处理器,使用软件浮点运算,很古老的手机是这架构, 出现在2000年左右 。(32位)armeabi-v7a:第七代ARM处理器,使用硬件浮点运算,2018年以前手机主流架构, 2007年开始出现 。(32位)arm64-v8a:第八代64位处理器,当前主流架构, 2014年左右出现。(64位)x86/x86-64:Intel处理器,Android模拟器用得比较多。 
X86_64与X64都是讲的同一个东西(64位) 。x86(32位)每一种CPU架构对应一个ABI,ABI定义了二进制文件(比如SO)如何运行在相应的系统平台。

详细介绍:

https://blog.csdn.net/wenzhi20102321/article/details/137064391

看看so和cpu框架,看看时间,大概就知道为啥现在应用都是64位框架的了,不可能再用十几年前的应用了吧。

如果真的使用32位的cpu框架,

apk下面的so目录是: lib/armeabi-v7a

system下面的so目录是 :system/lib

有的系统会在system/lib 和 system/lib64 都放so,防止运行的是32位的cpu框架的应用报错。

3、Android 系统源码项目加载预编好的so库

本来以为只是介绍一下编译使用的Android.mk或者Android.bp就可以了,

但是事实有点出乎意料,总结下来发现收获了一些知识点;

普通应用开发不一定用到这个知识,但是系统编译开发会用到这个知识,并且有的相关文件还不好解决。

https://blog.csdn.net/wenzhi20102321/article/details/141968262

这篇关于Android 源码中jni项目 加载so目录小结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1144052

相关文章

部署Vue项目到服务器后404错误的原因及解决方案

《部署Vue项目到服务器后404错误的原因及解决方案》文章介绍了Vue项目部署步骤以及404错误的解决方案,部署步骤包括构建项目、上传文件、配置Web服务器、重启Nginx和访问域名,404错误通常是... 目录一、vue项目部署步骤二、404错误原因及解决方案错误场景原因分析解决方案一、Vue项目部署步骤

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内

SpringBoot中使用 ThreadLocal 进行多线程上下文管理及注意事项小结

《SpringBoot中使用ThreadLocal进行多线程上下文管理及注意事项小结》本文详细介绍了ThreadLocal的原理、使用场景和示例代码,并在SpringBoot中使用ThreadLo... 目录前言技术积累1.什么是 ThreadLocal2. ThreadLocal 的原理2.1 线程隔离2

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

关于Spring @Bean 相同加载顺序不同结果不同的问题记录

《关于Spring@Bean相同加载顺序不同结果不同的问题记录》本文主要探讨了在Spring5.1.3.RELEASE版本下,当有两个全注解类定义相同类型的Bean时,由于加载顺序不同,最终生成的... 目录问题说明测试输出1测试输出2@Bean注解的BeanDefiChina编程nition加入时机总结问题说明

Spring AI Alibaba接入大模型时的依赖问题小结

《SpringAIAlibaba接入大模型时的依赖问题小结》文章介绍了如何在pom.xml文件中配置SpringAIAlibaba依赖,并提供了一个示例pom.xml文件,同时,建议将Maven仓... 目录(一)pom.XML文件:(二)application.yml配置文件(一)pom.xml文件:首

JS 实现复制到剪贴板的几种方式小结

《JS实现复制到剪贴板的几种方式小结》本文主要介绍了JS实现复制到剪贴板的几种方式小结,包括ClipboardAPI和document.execCommand这两种方法,具有一定的参考价值,感兴趣的... 目录一、Clipboard API相关属性方法二、document.execCommand优点:缺点:

Python创建Excel的4种方式小结

《Python创建Excel的4种方式小结》这篇文章主要为大家详细介绍了Python中创建Excel的4种常见方式,文中的示例代码简洁易懂,具有一定的参考价值,感兴趣的小伙伴可以学习一下... 目录库的安装代码1——pandas代码2——openpyxl代码3——xlsxwriterwww.cppcns.c

MyBatis-Flex BaseMapper的接口基本用法小结

《MyBatis-FlexBaseMapper的接口基本用法小结》本文主要介绍了MyBatis-FlexBaseMapper的接口基本用法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具... 目录MyBATis-Flex简单介绍特性基础方法INSERT① insert② insertSelec