UnsatisfiedLinkError X.so is 64-bit instead of 32-bit之Android 64 bit SO 加载原理
2016-11-30 17:38
609 查看
今天用户反馈应用闪退崩溃了。然后找呀找…
过程原来是这样的:
应用本身是个Android App,感觉这是费话呵,引用了一个JAVA项目。在应用启动后会将App res/raw中的动态库压缩包复制到Sdcard进行解压,然后使用System.load(libPath)加载。libPath是根据System.getProperty(“os.arch”);获取当前处理器的架构动态匹配出来的(例:mnt/sdcard/mylib/armv7l/a.so)。
前期开发时只放了armv7l的动态库,当一些有钱的客户买了新的Android设备后,如果处理器是aarch64的架构,问题就来了,加载mnt/sdcard/mylib/aarch64/a.so时,这个路径下是没有so的。
与 此同时App项目的lib/目录还是有其它so的。
Canney原创,转载请注明:http://blog.csdn.net/canney_chen/article/details/50633982
为解决上面的这个问题,那当然是再生成一个aarch64的动态库。当这一些就绪后就出了如题UnsatisfiedLinkError a.so is 64-bit instead of 32-bit 的错误。
从错误信息可以看出当前的a.so为64 bit这个是没有问题的。
但从 instead of 32-bit可以看出当前的环境并不是64 bit的而是32 bit。
于是找到了下面的这个资料:http://malideveloper.arm.com/downloads/01_Demystifying_64-bit_development_on_Android_Ramin_Zaghi.pdf
这份文档第一部分写了ARM 64-bit Architecture in Android™,其中的一个图拉出来看看。
All Apps are forked from a background Virtual Machine (VM) process called Zygote
Multilib devices run two Zygotes (a 32-bit one and a 64-bit one) in parallel!
When an application is launched on a 64-bit system
If it contains a supported 64-bit library, it runs as a 64-bit process against the loaded system
If it contains a supported 32-bit library, it is launched as a 32-bit process
Applications with no native code are launched using the default virtual machine (typically 64-bit)
上面这段话是原文对上图的说明,能看懂的就略过我下面的解析。
所有的app运行都是由Zygote进程创建VM再运行的。
支持多种库运行的设备,有两个Zytgote(一个32-bit,一个64-bit)进程同时运行。
当App运行在64-bit 系统上时:
如果App包含64-bit库,它将运行在一个64位进程中,即VM是由Zytgote 64创建的(图中的2)。
如果App包含32-bit 库,它将运行在一个32 bit进程中,即VM是由Zytgote创建的(图中的3)
如果App不包含本地库,它将默认运行在64 bit进程中。
对于图中的1,4,5位置表明系统默认运行在64 bit进程中。
有了上面的基础后,对错误就不难理解了:
1. App是否包含本地库、32/64bit是从App/libs目录下进行扫描的。
2. 我的应用在App/libs目录下只有32 bit的so。根据上面的第二条可以判断出我的应用Zytgote(32)创建的VM加载起来的。即32-bit进程在运行。
3. 动态从sdcard加载的a.so(64-bit)对应用启动来说并不知道。
综合上面的分析得出错误产生的原因。
方法1:所有so都增加aarch64的so(动态加载及App/libs下的so)。
方法2:所有so都使用32-bit的(即把原来匹配aarch64目录下的so,删除换成32位的或将aarch64直接匹配到32位的arm7l目录)。
aarch64是armv8架构下的64-bit执行状态, 当然同版本下还有aarch32 32-bit执行状态,具体可以查看[ARMv8
百度百科]
64-bit/32-bit 动态库不能混用
64-bit处理器可以向下兼容32-bit指令集,即可以运行32-bit动态库
当App中没有使用到64-bit处理器特性且动态库容量很大时可以考虑只使用32-bit动态库,这样可以减小安装包的大小。
Canney原创,转载请注明:http://blog.csdn.net/canney_chen/article/details/50633982
过程原来是这样的:
还是说下项目背景
应用本身是个Android App,感觉这是费话呵,引用了一个JAVA项目。在应用启动后会将App res/raw中的动态库压缩包复制到Sdcard进行解压,然后使用System.load(libPath)加载。libPath是根据System.getProperty(“os.arch”);获取当前处理器的架构动态匹配出来的(例:mnt/sdcard/mylib/armv7l/a.so)。前期开发时只放了armv7l的动态库,当一些有钱的客户买了新的Android设备后,如果处理器是aarch64的架构,问题就来了,加载mnt/sdcard/mylib/aarch64/a.so时,这个路径下是没有so的。
与 此同时App项目的lib/目录还是有其它so的。
Canney原创,转载请注明:http://blog.csdn.net/canney_chen/article/details/50633982
为解决上面的这个问题,那当然是再生成一个aarch64的动态库。当这一些就绪后就出了如题UnsatisfiedLinkError a.so is 64-bit instead of 32-bit 的错误。
以下是对产生这个错误进行的相关研究
从错误信息可以看出:
从错误信息可以看出当前的a.so为64 bit这个是没有问题的。但从 instead of 32-bit可以看出当前的环境并不是64 bit的而是32 bit。
当前设备是64 bit为什么运行的程序是32 bit环境??
于是找到了下面的这个资料:http://malideveloper.arm.com/downloads/01_Demystifying_64-bit_development_on_Android_Ramin_Zaghi.pdf 这份文档第一部分写了ARM 64-bit Architecture in Android™,其中的一个图拉出来看看。
How Does It All Work?
All Apps are forked from a background Virtual Machine (VM) process called ZygoteMultilib devices run two Zygotes (a 32-bit one and a 64-bit one) in parallel!
When an application is launched on a 64-bit system
If it contains a supported 64-bit library, it runs as a 64-bit process against the loaded system
If it contains a supported 32-bit library, it is launched as a 32-bit process
Applications with no native code are launched using the default virtual machine (typically 64-bit)
上面这段话是原文对上图的说明,能看懂的就略过我下面的解析。
所有的app运行都是由Zygote进程创建VM再运行的。
支持多种库运行的设备,有两个Zytgote(一个32-bit,一个64-bit)进程同时运行。
当App运行在64-bit 系统上时:
如果App包含64-bit库,它将运行在一个64位进程中,即VM是由Zytgote 64创建的(图中的2)。
如果App包含32-bit 库,它将运行在一个32 bit进程中,即VM是由Zytgote创建的(图中的3)
如果App不包含本地库,它将默认运行在64 bit进程中。
对于图中的1,4,5位置表明系统默认运行在64 bit进程中。
有了上面的基础后,对错误就不难理解了:
1. App是否包含本地库、32/64bit是从App/libs目录下进行扫描的。
2. 我的应用在App/libs目录下只有32 bit的so。根据上面的第二条可以判断出我的应用Zytgote(32)创建的VM加载起来的。即32-bit进程在运行。
3. 动态从sdcard加载的a.so(64-bit)对应用启动来说并不知道。
综合上面的分析得出错误产生的原因。
解决办法就是:
方法1:所有so都增加aarch64的so(动态加载及App/libs下的so)。方法2:所有so都使用32-bit的(即把原来匹配aarch64目录下的so,删除换成32位的或将aarch64直接匹配到32位的arm7l目录)。
总结一下
aarch64是armv8架构下的64-bit执行状态, 当然同版本下还有aarch32 32-bit执行状态,具体可以查看[ARMv8百度百科]
64-bit/32-bit 动态库不能混用
64-bit处理器可以向下兼容32-bit指令集,即可以运行32-bit动态库
当App中没有使用到64-bit处理器特性且动态库容量很大时可以考虑只使用32-bit动态库,这样可以减小安装包的大小。
Canney原创,转载请注明:http://blog.csdn.net/canney_chen/article/details/50633982
相关文章推荐
- UnsatisfiedLinkError X.so is 64-bit instead of 32-bit之Android 64 bit SO加载机制
- UnsatisfiedLinkError X.so is 64-bit instead of 32-bit之Android 64 bit SO加载机制
- UnsatisfiedLinkError X.so is 64-bit instead of 32-bit之Android 64 bit SO加载机制
- 解决Android 错误 couldn't find "xxx.so" is 32-bit instead of 64-bit
- Caused by java.lang.UnsatisfiedLinkError: dlopen failed: "/data/app/com.google.android.webview-1/lib/arm/libwebviewchromium.so" is 32-bit instead of 64-bit
- React Native解决"libgnustl_shared.so" is 32-bit instead of 64-bit"报错问题
- Android -- is 32-bit instead of 64-bit
- Android -- is 32-bit instead of 64-bit
- UnsatisfiedLinkError:libwebviewchromium.so is 32-bit instead of 64-bit
- UnsatisfiedLinkError: dlopen "/data/data/<package>/app_jni_lib/libxxx.so is 32-bit instead of 64-bit
- React java.lang.UnsatisfiedLinkError: dlopen failed: "/data/data/com.edaixi.activity/lib-main/libgnustl_shared.so" is 32-bit instead of 64-bit
- UnsatisfiedLinkError:libwebviewchromium.so is 32-bit instead of 64-bit
- Android studio 2.2.2 中使用 so 文件出现:dlopen failed: "/xxx.so" is 32-bit instead of 64 bit
- is 32-bit instead of 64-bit动态库错误分析
- is 32-bit instead of 64-bit动态库错误分析
- /libs/libBaiduMapSDK_base_v4_5_2.so" is 32-bit instead of 64-bit
- is 32-bit instead of 64-bit动态库错误分析
- loadExceptionjava.lang.UnsatisfiedLinkError:is 32-bit instead of 64-bit
- Android6.0 高通平台 "is 32-bit instead of 64-bit" 问题
- 共用SystemUid应用安装后出现 is 32-bit instead of 64-bit