Crash 日志:
java.lang.UnsatisfiedLinkError: dlopen failed: "/data/data/com.ireader.plug.sdk/ireader_plugins/lib/armeabi/lib***.so"
is 32-bit instead of 64-bit
at java.lang.Runtime.loadLibrary0(Runtime.java:1016)
at java.lang.System.loadLibrary(System.java:1657)
問題分析:
首先看log, 報錯為:so打開失敗,因為lib***.so 是32位的so,而不是64位的。
補充:
Android 程序 運行起來,要么只加載32位的so, 要么只加載64 位的so. 是不能混合加載的。
常見的兩種情況如下:
第一種情況:
對於一個android程序,如果程序沒有用到任何so,假如程序跑在64位的手機上,虛擬機默認加載64位的so。這時候,如果你加載了32位的so,就會報錯。反之,如果程序跑在32位的手機上,虛擬機默認只加載32位的so.
可能有同學有疑問,既然我的程序里面沒有任何的so, 跑在了64位的手機上,這種情況下怎么會加載32位的so呢?我的程序里面是沒有so 的啊。沒錯,你的apk 里面是沒有任何的so,但是如果你的項目中使用了插件技術,插件apk 里面有32 位的so,這時候就會掛掉了。
解決方法:
在你的項目里面建立一個armeabi 的文件夾,里面放一個文件。文件名字叫做fix.so。這個so 可以是0kb,但是一定要有。這樣,程序跑在64位的手機上,發現你只有armeabi 的文件夾,那么就會使用32 位的虛擬機,這時候,加載你插件里面的so,就不會有問題了。
第二種情況:
如果程序里面有so, 並且有arm64-v8a 或者x64 的文件夾,也有armeabi 的文件夾,運行在64位的手機上,會默認使用arm64-v8a 或者x64 文件夾里面的so. 這時候,如果有些so 沒有arm64-v8a ,就會報錯找不到so。 雖然你在armeabi 文件夾里面有。
如果是這種情況,那么直接把 arm64-v8a 的so 刪除掉,只留下armeabi 的so。 因為armebai 兼容所有類型的處理器。當然你也可以把缺少的64位的so 編譯一下。
我們項目具體場景:
我們是做插件sdk 給第三方接入的。我們會讓第三方接入一個apk文件,里面只有armeabi 的so.
還有一個libmerge.so 用於插件增量更新。但是有些廠商不願意動態更新,我們定的方案是如果不需要增量更新這個功能,程序里面可以沒有libmerge.so 。
早期的時候,手機還都是32位的,所以,沒有問題。但是現在都是64位的手機,有的廠商自己apk 沒有任何的so, 跑在64為手機上,上來就掛。java.lang.UnsatisfiedLinkError: dlopen failed * is 32-bit instead of 64-bit
他們反饋在有些手機會出現,有些手機可以正常運行。當然,可以運行的都是32位手機,不可以的都是64位的手機。
這時候,我們讓廠商放在armeabi 文件夾下一個fix.so。雖然是一個空文件,但是程序就可以跑起來。這樣,程序跑在64位的手機上,發現你只有armeabi 的文件夾,那么就會去加載32 位的so,這時候,加載你插件里面的so,就不會有問題了。
知識補充:
如何查看android cpu是32位還是64位?
adb shell getprop ro.product.cpu.abi
C:\Users\zy>adb shell getprop ro.product.cpu.abi
arm64-v8a
C:\Users\zy>adb shell getprop ro.product.cpu.abi
armeabi-v7a
可以看到手機默認的so 文件夾。arm64-v8a 是64位的。另外,一般手機內存超過4G 都是64位的,因為32支持的最大內存是4G.
參考: