2019-03-25 使用dlopen动态加载JNI库失败,提示
问题描述:
如题,Android项目中使用了FFmpeg封装成的JNI文件libffmpeg.so,在Google API 23之前,该错误还只是一个警告,并不影响使用,加上上一位工程师不在意和疏忽,没有在编译的时候添加-fPIC来去掉此警告,最近,因为Google的一些隐私政策更新,导致需要更新App,由于新App被要求compileSdkVersion必须在API 26以上,导致此问题变得突出,因为在API 23后,该警告被升级为错误,并引起崩溃,崩溃的堆栈信息如下:
2019-03-25 11:58:42.053 10374-10913/? E/AndroidRuntime: FATAL EXCEPTION: Thread-40
Process: com.hhws.singapore, PID: 10374
java.lang.UnsatisfiedLinkError: dlopen failed: "/data/app/com.hhws.singapore-p5l_BGv3e_OO-QO2VPlwGQ==/lib/arm/libffmpeg.so" has text relocations
at java.lang.Runtime.loadLibrary0(Runtime.java:1016)
at java.lang.System.loadLibrary(System.java:1660)
at com.ffmpeg.H264Decode.<clinit>(H264Decode.java:43)
at com.ffmpeg.H264Decode.Initlization(Native Method)
at com.hhws.lib360.video.PlaySurfaceView.videoDecode(PlaySurfaceView.java:223)
at com.hhws.lib360.video.PlaySurfaceView.access$000(PlaySurfaceView.java:52)
at com.hhws.lib360.video.PlaySurfaceView$1.run(PlaySurfaceView.java:517)
环境:
Window 7:
Android Studio 3.3.2
minSdkVersion=19
compileSdkVersion=26
buildToolsVersion=27.0.3
Mac OS 10.14.3
Android Studio 3.3.2
minSdkVersion=19
compileSdkVersion=26
buildToolsVersion=27.0.3
方法尝试:
1. 重新编译
寻找libffmpeg.so的源码,尝试进行重新编译
失败
,持有源码的员工离职太久,并且不是很配合,暂时不考虑请求他帮助
2.编译官方FFmpeg
因为libffmpeg.so的库文件名与官方的名字一样,尝试下载官方版本重新编译后接入
失败
,生成官方版本的libffmpeg.so后尝试替换,提示没有发现对应方法实现:
2019-03-25 10:31:53.774 7325-8452/? E/AndroidRuntime: FATAL EXCEPTION: Thread-76
Process: com.hhws.singapore, PID: 7325
java.lang.UnsatisfiedLinkError: No implementation found for long com.ffmpeg.H264Decode.Initlization() (tried Java_com_ffmpeg_H264Decode_Initlization and Java_com_ffmpeg_H264Decode_Initlization__)
at com.ffmpeg.H264Decode.Initlization(Native Method)
at com.hhws.lib360.video.PlaySurfaceView.videoDecode(PlaySurfaceView.java:223)
at com.hhws.lib360.video.PlaySurfaceView.access$000(PlaySurfaceView.java:52)
at com.hhws.lib360.video.PlaySurfaceView$1.run(PlaySurfaceView.java:517)
在命令窗口使用nm -D libffmpeg.so > nmlibffmpeg.txt
对比旧的JNI库和官方方法生成的libffmpeg.so文件的符号表:
0001d641 T Java_com_ffmpeg_H264Decode_DecodeH264Frame
0001d4f9 T Java_com_ffmpeg_H264Decode_Destory
0001d4b9 T Java_com_ffmpeg_H264Decode_GetHeight
0001d521 T Java_com_ffmpeg_H264Decode_GetPixels
0001d499 T Java_com_ffmpeg_H264Decode_GetWidth
0001d6d1 T Java_com_ffmpeg_H264Decode_GetYUVPixels
0001d761 T Java_com_ffmpeg_H264Decode_Initlization
0001d4e5 T Java_com_ffmpeg_isKeyFrame
可发现上一名员工修改了FFmpeg官方的代码添加了这8
个方法,并且自己做了优化,使Java调用时不需要包含ffmpeg的头文件信息,但是该工程师没有交代好这个ffmpeg库的源码信息,导致现在无法进行重新编译以修复问题。
3.以FFmpeg的官方方法适配目前项目的需求(还未实践)
项目中使用的主要是音视频的编解码功能,应该有相关参考的资料,可以尝试的方向
4.向该部分JNI制作者请教
这个就比较尴尬了~而且不知道会不会被要求收费,相当尴尬