今天遇到一个问题,so库调用报错,记录一下。
日志如下:
java.lang.UnsatisfiedLinkError: No implementation found for long org.webrtc.Histogram.nativeCreateCounts(java.lang.String, int, int, int) (tried Java_org_webrtc_Histogram_nativeCreateCounts and Java_org_webrtc_Histogram_nativeCreateCounts__Ljava_lang_String_2III)
at org.webrtc.Histogram.nativeCreateCounts(Native Method)
at org.webrtc.Histogram.createCounts(Histogram.java:30)
at org.webrtc.Camera1Session.<clinit>(Camera1Session.java:31)
at org.webrtc.Camera1Capturer.createCameraSession(Camera1Capturer.java:31)
at org.webrtc.CameraCapturer$5.run(CameraCapturer.java:329)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:179)
at android.os.HandlerThread.run(HandlerThread.java:61)No implementation found for long
org.webrtc.Histogram.nativeCreateCounts(java.lang.String, int, int, int) (tried Java_org_webrtc_Histogram_nativeCreateCounts and Java_org_webrtc_Histogram_nativeCreateCounts__Ljava_lang_String_2III)
1,问题是什么:
先要理解这个含义是指执行Histogram.java里的native修饰的方法nativeCreateCounts时,未找到对应的native层方法(so库里的)。
2,这个执行流程是很明确的:
代码里先加载so库,java层执行native修饰的native方法,然后通过jni调用到so库里的对应方法。
3,其实思路很简单,按照上面的执行流程,对应从三个方面考虑:
1),确认Histogram类nativeCreateCounts方法有没有被混淆。
从这个报错日志看是未被混淆的,也可以从mapping.txt或者直接项目中搜索对应的Histogram.class,看nativeCreateCounts是否被混淆,这里可以看到方法名是nativeCreateCounts,没有被混淆的。如果有混淆,可以使用下面解决混淆的问题。
//保留native方法的类名和方法名
-keepclasseswithmembernames class * {
native <methods>;
}
2),确认so库是否有效并被加载。
- apk里有木有这个so库,可以解压缩apk查看lib文件夹下是否有对应的so库,
- 如果有这个库,查看对应的cpu架构是不是对的,
1、adb shell
2、cat /proc/cpuinfo
显示下面:
Processor : AArch64 Processor rev 14 (aarch64)
表示arm64-v8a的(可以向下兼容v5\v6\v7)。
- 确认so被加载,System.loadLibrary(“xxxxx”)被调用。
3),确认so库有木有这个方法Java_org_webrtc_Histogram_nativeCreateCounts__Ljava_lang_String_2III。
使用命令nm -D xxx.so,查看有木有对应的方法。
4,实例分析
针对日志输出的这个crash问题,按照上面的都走了一遍,最后有点绝望,都没问题呀,关键只是部分手机有这个问题。
最后发现问题点是:
System.loadLibrary(“xxxxx”)这个执行在子线程,而ava_org_webrtc_Histogram_nativeCreateCounts这个方法调用是在另一个线程,所以当cpu负载比较重,线程阻塞的时候就会出现先调用了方法,然后才去加载so库,就会出现这个问题了。修改System.loadLibrary(“xxxxx”)位置后OK。