当前位置:首页 » JAVA技术教程

Android Crash解决方案之java.lang.UnsatisfiedLinkError

2016-07-13 10:55 本站整理 浏览(33)
该错误类型较多,以下进行分类:
1、java.lang.UnsatisfiedLinkError : dlopen failed: library //dlopen打开失败
2、java.lang.UnsatisfiedLinkError :findLibrary returned null //找不到library
3、java.lang.UnsatisfiedLinkError : Native method not found //找不到对应函数
4、java.lang.UnsatisfiedLinkError :Cannot load library: load_library //无法load library
出现原因:
显然出现上述崩溃的根本原因是
1)So无法加载,可能是So不存在等原因
2)So正常加载,但是没有找到相应的函数
针对第二个原因,显然相对来说很容易排查,而且在开发中,这样的函数调用必然会在编译时和debug模式下进行测试,所以这种原因产生的概率很小。
那么下面主要总结几类“So无法加载”而导致上述崩溃的几种原因:
1.生成的So本身缺陷
一个简单的例子:
crash堆栈:
120 20008-20008/com.netease.nis.apptestunit E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.UnsatisfiedLinkError: Cannot load library: find_library(linker.cpp:889): "/data/data/com.netease.nis.apptestunit/app_lib/libdemo.so" failed to load previously
 at java.lang.Runtime.load(Runtime.java:340)
 at java.lang.System.load(System.java:521)
 at com.netease.nis.bugrpt.ReLinker.loadLibrary(ReLinker.java:76)
 at com.example.crash.MainActivity.onCreate(MainActivity.java:272)
 at android.app.Activity.performCreate(Activity.java:5220)
 at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1086)
 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2193)
 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2279)
 at android.app.ActivityThread.access$600(ActivityThread.java:142)
 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1272)
 at android.os.Handler.dispatchMessage(Handler.java:99)
 at android.os.Looper.loop(Looper.java:137)
 at android.app.ActivityThread.main(ActivityThread.java:5105)
 at java.lang.reflect.Method.invokeNative(Native Method)
 at java.lang.reflect.Method.invoke(Method.java:511)
 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
 at dalvik.system.NativeStart.main(Native Method)

解决方法:
查看原项目Application.mk
发现
APP_STL := gnustl_shared

APP_STL 可用值
system 系统默认
stlport_static - 使用STLport作为静态库
stlport_shared - 使用STLport 作为共享库
gnustl_static - 使用GNU libstdc++ 作为静态库
gnustl_shared - 使用GNU libstdc++ 作为共享库
原方案使用的是共享库,这不一定都支持所有的机型,改用静态库gnustl_static 问题解决。
对应的在Android Studio中:需要将共享库改用静态库gnustl_static
这一类关于so编译共享库问题,需要进行检查。
上述例子只是一个简单的例子,可能在So编译生成时,由于没有考虑共享库的机型匹配等原因导致UnsatisfiedLinkError崩溃,其次是64位32位系统架构问题,也可能导致UnsatisfiedLinkError崩溃。
2.手机设备没有空间
在So正确生成情况下,会根据设置的支持So库框架生成对应的库。
在Android系统中,当我们安装apk文件的时候,lib目录下的so文件会被解压到app的原生库目录,一般来说是放到/data/data/<package-name>/lib目录下
当准备加载native层的so时,虽然在APK中有对应的so文件,但是由于手机设备没有足够的空间加载该so,导致加载失败,产生上述崩溃。
3.So加载库的选择错误
倘若So正确生成,且手机空间充足,那么如上所述,在Android系统中,当我们安装apk文件的时候,lib目录下的so文件会被解压到app的原生库目录,一般来说是放到/data/data/<package-name>/lib目录下。但是根据系统和CPU架构的不同,其拷贝策略也是不一样的。倘若不正确地配置了so文件,比如某些app使用第三方的so时,只配置了其中某一种CPU架构的so,可能会造成app在某些机型上的适配问题,产生上述崩溃。
具体解决方案请参考链接:
技术分享 / Android
系统安装 apk 时解压 so 的逻辑问题 :http://crash.163.com/index.do#news/!newsId=5
技术分享/Android 加载 SO 库 UnsatisfiedLinkError 错误的原因及解决方案:http://crash.163.com/index.do#news/!newsId=4