关于Android N不能加载.so库的相关问题分析

一.问题描述

本来希望在android系统上做一个.so库,然后app可以调用。

这个so库是调用surfaceflinger及skia库的接口实现的功能。

结果在实际加载调用时却报这样的错:

E linker : library "/system/lib64/libXXX.so" ("/system/lib64/libXXX.so") needed or dlopened by "/system/lib64/libXXXXXX.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="", permitted_paths="/data:/mnt/expand:/data/data/com.android.XXX"]

 

但事实上,我写过可执行文件来带调这个库,本身没什么问题。

 

 

二.解决过程

本来以为是没有加载对路径,然后故意写了个没有的.so库。结果提示找不到(dlopen failed: library "libXXX.so" not found),所以排除路径的问题。

 

然后查了下问题,发现是这样的:

https://blog.csdn.net/wjskeepmaking/article/details/70153995

大概是说是Android N才有的新特征。

 

于是尝试下发现他好像确实是开放了部分库,dlopen打开系统目录下的lib时,有部分能打开,有部分不能打开,但通过ADB查看路径下的库,其实都是在的。所以这里验证了有一个list来管理的事实。

 

后来又搜了一下解决方式:

https://blog.csdn.net/ngyzqf/article/details/78991929

 

然后我尝试把自己的库加入到public.libraries.txt这个list里面,然后就可以调用了。

 

 

三.后续

本来以为问题到这里快乐的解决了,但出现一堆问题也让人头疼,这里决定再次研究一下。

一个问题时我将我自己的库加到list里面后android系统开机会有一定几率崩溃,导致系统不能启动。一开始也不知道时什么原因,后来某个巧合下发现如果list里的lib库不存在系统就会启动不起来,所以可能是我的问题?????之前每次都急急忙忙的刷固件了,没仔细研究debug信息。

 

第二个问题是,需求改成做成以app的形式发布。。这下为难了,虽然知道将依赖系统层的库以和app的形式一起发布不太合理,不过既然老板这么要求了。还是先照做吧。

所以首要目标是将so库打包进apk中。

最简单的方式将我的so库拉到安卓应用工程的libs目录下。

然后用cmakelist连接进去。

然后就会报错,报找不到我的依赖库。然后为了测试就把编译器报少的依赖库一个个加进去,加到最后发现依赖的越来越多,然后还是又没找到的。这时候感觉已经很不靠谱了。谁装个APP把系统的库都全部打包进去呢?应该也又第三方的库有部分依赖系统库的,但是他们是可以调用成功,应该是自己姿势不对吧。

 

然后就开始找问题。回到了最之前,发现缺的库都是makefile里链接的库。

第一反应是不是android没把什么查找路径配置进去,又绕回了最先的弯。不过两次情况是不大一样的。第一次是将库放在/system/lib下面调用失败,第二次是打包进apk的情况。

网上找了一下怎么把路径配置到android里面:

搜到了这个:https://www.cnblogs.com/jukan/p/5786765.html

虽然没用android,但可以解释下大概的思路:就是获得应用的一个全局类对象。然后这个对象里包含着应用的配置属性,然后获得对应属性的值,然后修改,这里查了一下用的好像是反射机制。然后就套着把系统路径加进去了。(这里需要加下,博客没说清楚,参数里Application的输入参数可以在主activity里通过 this.getApplication() 获得。同时,可能是版本问题nativeLibraryDirectories.get(pathList);回来的对象是个ArrayList<File>类型)

加完之后发现没什么反应,依旧报错。然后仔细看了一下那个对象中的属性。发现他有好几个pathList,然后他们全部包含了系统目录,除了按那个博客上修改的那个属性没有。突然感觉是不是自己方向又错了(后面也证明这个确实不是问题所在)。

 

然后我开始怀疑其是不是编译的问题(没加什么参数造成的)。但是回想了一下之前用共享库的经历。linux下可以用ldd查看他的依赖库。如果没有找到,他会报not found library,然后添加库路径进LD_LIBRARY_PATH就可以找到了。可见这里和编译的参数问题也不大。

这里补充一点:android源码下生成的库用ldd时看不到依赖的,原因是库的架构不一样。可以用readelf查看或者 aarch64-linux-android-readelf 命令查看。

 

查看到他的依赖库之后和我之前编译生成共享库的makefile联系起来(其实是一样的)。发现一个问题,好像在在最前面的log库没有找不到。

 

!!!!瞬间想明白了。可以去证明一下。

 

把自己生成的库的依赖库,全部添加到public.libraries.txt这个list中,编译,运行就通过了。看来问题依旧出在N版本以上的这个list上。

 

如果是这样。很可能是加载的时候调用了dlopen的查找限制限制了可链接的库文件。如果是编译时链接的链接,在调用System.loadLibrary()来加载库时底层也是个dlopen。

 

-------------------------------------------------------------------------------------------------------

 

针对前面放在/etc/public.libraries.txt中会崩溃的问题。

又做了以下尝试,发现可以使用:

为了不修改系统的配置,所以把自己生成的.so库加入到/vendor/etc/public.libraries.txt中。而/etc/public.libraries.txt未做更改。结果用dlopen打开也可以行得通。

 

 

问题到这里算是基本解决了。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值