1、 崩溃日志
日志 1
关键日志
Failed to register native method com.bykv.vk.component.ttvideo.player.TTPlayer._close(J)V in base.apk
ttvideo :其中 tt 标识头条,可知是头条广告 SDK Failed to register native method:看样子是 so 相关详细日志
Failed to register native method com.bykv.vk.component.ttvideo.player.TTPlayer._close(J)V in base.apk
----- class 'Lcom/bykv/vk/component/ttvideo/player/TTPlayer;
' cl=0x12d6c3a0 -----
objectSize=941 (736 from super)
access=0x0008.0001
super='java.lang.Class' (cl=0x0)
vtable (24 entries, 11 in super):
0: void com.bykv.vk.component.ttvideo.player.TTPlayer.A()
1: int com.bykv.vk.component.ttvideo.player.TTPlayer.a(int, float)
2: int com.bykv.vk.component.ttvideo.player.TTPlayer.b(int, int)
3: int com.bykv.vk.component.ttvideo.player.TTPlayer.c(int, long)
4: int com.bykv.vk.component.ttvideo.player.TTPlayer.d(int, java.lang.String)
5: int com.bykv.vk.component.ttvideo.player.TTPlayer.e(android.view.Surface)
6: void com.bykv.vk.component.ttvideo.player.TTPlayer.g(float, float)
7: void com.bykv.vk.component.ttvideo.player.TTPlayer.h(int)
8: void com.bykv.vk.component.ttvideo.player.TTPlayer.i(long)
9: void com.bykv.vk.component.ttvideo.player.TTPlayer.j(com.bykv.vk.component.ttvideo.player.f)
10: void com.bykv.vk.component.ttvideo.player.TTPlayer.l(java.lang.String, int)
11: float com.bykv.vk.component.ttvideo.player.TTPlayer.m(int, float)
12: int com.bykv.vk.component.ttvideo.player.TTPlayer.n(int, int)
13: long com.bykv.vk.component.ttvideo.player.TTPlayer.o(int, long)
14: void com.bykv.vk.component.ttvideo.player.TTPlayer.p(int)
15: void com.bykv.vk.component.ttvideo.player.TTPlayer.r(java.lang.String)
16: int com.bykv.vk.component.ttvideo.player.TTPlayer.s()
17: void com.bykv.vk.component.ttvideo.player.TTPlayer.t(int)
18: int com.bykv.vk.component.ttvideo.player.TTPlayer.u()
19: java.lang.String com.bykv.vk.component.ttvideo.player.TTPlayer.v(int)
20: int com.bykv.vk.component.ttvideo.player.TTPlayer.w()
21: int com.bykv.vk.component.ttvideo.player.TTPlayer.x()
22: int com.bykv.vk.component.ttvideo.player.TTPlayer.y()
23: int com.bykv.vk.component.ttvideo.player.TTPlayer.z()
direct methods (35 entries):
0: void com.bykv.vk.component.ttvideo.player.TTPlayer.()
1: void com.bykv.vk.component.ttvideo.player.TTPlayer.(android.content.Context, long)
2: void com.bykv.vk.component.ttvideo.player.TTPlayer.B()
3: long com.bykv.vk.component.ttvideo.player.TTPlayer._create(android.content.Context, int, java.lang.String)
4: int com.bykv.vk.component.ttvideo.player.TTPlayer._getCurrentPosition(long)
5: int com.bykv.vk.component.ttvideo.player.TTPlayer._getDuration(long)
6: float com.bykv.vk.component.ttvideo.player.TTPlayer._getFloatValue(long, int, float)
7: int com.bykv.vk.component.ttvideo.player.TTPlayer._getIntValue(long, int, int)
8: long com.bykv.vk.component.ttvideo.player.TTPlayer._getLongValue(long, int, long)
9: java.lang.String com.bykv.vk.component.ttvideo.player.TTPlayer._getStringValue(long, int)
10: int com.bykv.vk.component.ttvideo.player.TTPlayer._getVideoHeight(long)
11: int com.bykv.vk.component.ttvideo.player.TTPlayer._getVideoWidth(long)
12: int com.bykv.vk.component.ttvideo.player.TTPlayer._isLooping(long)
13: int com.bykv.vk.component.ttvideo.player.TTPlayer._isPlaying(long)
14: int com.bykv.vk.component.ttvideo.player.TTPlayer._pause(long)
15: int com.bykv.vk.component.ttvideo.player.TTPlayer._prepare(long)
16: void com.bykv.vk.component.ttvideo.player.TTPlayer._release(long)
17: int com.bykv.vk.component.ttvideo.player.TTPlayer._reset(long)
18: int com.bykv.vk.component.ttvideo.player.TTPlayer._seek(long, int)
19: void com.bykv.vk.component.ttvideo.player.TTPlayer._setCacheFile(long, java.lang.String, int)
20: void com.bykv.vk.component.ttvideo.player.TTPlayer._setDataSource(long, java.lang.String)
21: void com.bykv.vk.component.ttvideo.player.TTPlayer._setDataSourceFd(long, int)
22: int com.bykv.vk.component.ttvideo.player.TTPlayer._setFloatValue(long, int, float)
23: int com.bykv.vk.component.ttvideo.player.TTPlayer._setIntValue(long, int, int)
24: int com.bykv.vk.component.ttvideo.player.TTPlayer._setLongValue(long, int, long)
25: void com.bykv.vk.component.ttvideo.player.TTPlayer._setLooping(long, int)
26: int com.bykv.vk.component.ttvideo.player.TTPlayer._setStringValue(long, int, java.lang.String)
27: void com.bykv.vk.component.ttvideo.player.TTPlayer._setSupprotSampleRates(int[], int)
28: int com.bykv.vk.component.ttvideo.player.TTPlayer._setVideoSurface(long, android.view.Surface)
29: void com.bykv.vk.component.ttvideo.player.TTPlayer._setVolume(long, float, float)
30: int com.bykv.vk.component.ttvideo.player.TTPlayer._start(long)
31: void com.bykv.vk.component.ttvideo.player.TTPlayer._stop(long)
32: java.lang.String com.bykv.vk.component.ttvideo.player.TTPlayer.f()
33: void com.bykv.vk.component.ttvideo.player.TTPlayer.k(java.lang.String)
34: void com.bykv.vk.component.ttvideo.player.TTPlayer.q(long)
static fields (4 entries):
0: int com.bykv.vk.component.ttvideo.player.TTPlayer.d
1: int[] com.bykv.vk.component.ttvideo.player.TTPlayer.e
2: java.lang.String com.bykv.vk.component.ttvideo.player.TTPlayer.f
3: boolean com.bykv.vk.component.ttvideo.player.TTPlayer.g
instance fields (3 entries):
0: long com.bykv.vk.component.ttvideo.player.TTPlayer.a
1: android.content.Context com.bykv.vk.component.ttvideo.player.TTPlayer.b
2: int com.bykv.vk.component.ttvideo.player.TTPlayer.c
日志 2
关键日志
E/DEBUG: Thread Name: 'tt_pangle_threa'
tt\_pangle\_threa:进一步确认属于是穿山甲(头条)广告 SDK 所在位置导致出现异常【一个关于混淆的 Native 崩溃分析】详细日志
E/DEBUG: --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
E/DEBUG: maps:
E/DEBUG: total lines: 2308, matched 708 lines, write 708 lines.
E/DEBUG: total address size: 1962624 kB
E/DEBUG: --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
E/DEBUG: Process Name: '【包名】'
E/DEBUG: Thread Name: 'tt_pangle_threa'
E/DEBUG: pid: 15925, tid: 16120>>> 【包名】 <<<
E/DEBUG: killed by pid: 15925, comm: 【包名】, uid: 12428.
E/DEBUG: signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
E/DEBUG:x00000000000000000x10000000000003ef8x20000000000000006x30000000000000008
E/DEBUG:x40000000000000199x50000007f882de940x604e82d887f000000x70000007f882de804
E/DEBUG:x80000000000000083x9ffffffffffffffdfx100000000000000000x110000000000000001
E/DEBUG:x12ffffffffffffffffx130000000001000000x140000000000000f7ex150000000000001fe3
E/DEBUG:x160000007f88320ed0x170000007f882ca510x180000000000000000x190000007f5c0d04f8
E/DEBUG:x200000000000000006x210000007f5c0d0450x22000000000000000bx2300000000000009dc
E/DEBUG:x24ffffffffffffffffx250000007f853fc730x260000007f85386540x270000007f5c0ca801
E/DEBUG:x280000007f8534c3dbx290000007f5c0ca730x300000007f882c79a0
E/DEBUG:sp0000007f5c0ca710pc0000007f882ca518pstate 0000000060000000
E/DEBUG:v000000000000000010000000000000000v10000007f5c0ca2900000007f5c0ca710
E/DEBUG:v200000000000000000000000000000000v300000000001000000000000000000000
E/DEBUG:v400000000000000000000000000000000v540100401401004014010040140100401
E/DEBUG:v600000000001000000000000000100000v7000000000000000000000000c1b00000
E/DEBUG:v800000000000000000000000000000000v900000000000000000000000000000000
E/DEBUG:v1000000000000000000000000000000000v1100000000000000000000000000000000
E/DEBUG:v1200000000000000000000000000000000v1300000000000000000000000000000000
E/DEBUG:v1400000000000000000000000000000000v1500000000000000000000000000000000
E/DEBUG:v1600000000000000000000000042756400v170000000000000000000000003fbb8000
E/DEBUG:v180000000000000000000000003e8ac000v19000000000000000000000000ebad8083
E/DEBUG:v20000000000000000000000000ebad8084v21000000000000000000000000ebad8085
E/DEBUG:v22000000000000000000000000ebad8086v23000000000000000000000000ebad8087
E/DEBUG:v24000000000000000000000000ebad8088v25000000000000000000000000ebad8089
E/DEBUG:v26000000000000000000000000ebad808av27000000000000000000000000ebad808b
E/DEBUG:v28000000000000000000000000ebad808cv29000000000000000000000000ebad808d
E/DEBUG:v30000000000000000000000000ebad808ev3100000000000000000000000000000001
E/DEBUG:fpsr 00000013fpcr 00000000
E/DEBUG:#00 pc 000000000006b518/system/lib64/libc.so (tgkill+8)
E/DEBUG:#01 pc 000000000006899c/system/lib64/libc.so (pthread_kill+64)
E/DEBUG:#02 pc 0000000000023ee8/system/lib64/libc.so (raise+24)
E/DEBUG:#03 pc 000000000001c96c/system/lib64/libc.so (abort+52)
E/DEBUG:#04 pc 000000000040b380/system/lib64/libart.so (_ZN3art7Runtime5AbortEv+352)
E/DEBUG:#05 pc 00000000000c2218/system/lib64/libart.so (_ZN3art10LogMessageD2Ev+1204)
E/DEBUG:#06 pc 000000000042d980/system/lib64/libart.so (_ZNK3art6Thread24AssertNoPendingExceptionEv+836)
E/DEBUG:#07 pc 0000000000101630/system/lib64/libart.so (_ZN3art11ClassLinker9FindClassEPNS_6ThreadEPKcNS_6HandleINS_6mirror11ClassLoaderEEE+68)
E/DEBUG:#08 pc 00000000003026bc/system/lib64/libart.so (_ZN3art3JNI9FindClassEP7_JNIEnvPKc+2780)
E/DEBUG:#09 pc 000000000005d8dc/data/app/【包名】-1/lib/arm64/libttmplayer_lite.so
E/DEBUG:#10 pc 000000000005e94c/data/app/【包名】-1/lib/arm64/libttmplayer_lite.so (JNI_OnLoad+360)
E/DEBUG:#11 pc 00000000002ccec8/system/lib64/libart.so (_ZN3art9JavaVMExt17LoadNativeLibraryEP7_JNIEnvRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEP8_jobjectP8_jstringPS9_+2136)
E/DEBUG:#12 pc 000000000000427c/system/lib64/libopenjdkjvm.so (JVM_NativeLoad+280)
E/DEBUG:#13 pc 000000000009be20/system/framework/arm64/boot.oat
E/DEBUG:--- --- --- ---
2、代码定位分析 由日志 1,那么获取到崩溃安装包和正常安装包,提取
com.bykv.vk.component.ttvideo.player.TTPlayer
类下的 Native
代码进一步分析崩溃包:
TTPlayer
类 Native
方法声明private final native long _create(Context context, int i, String str);
public static final native int _getCurrentPosition(long j);
public static final native int _getDuration(long j);
public static final native float _getFloatValue(long j, int i, float f);
public static final native int _getIntValue(long j, int i, int i2);
public static final native long _getLongValue(long j, int i, long j2);
public static final native String _getStringValue(long j, int i);
public static final native int _getVideoHeight(long j);
public static final native int _getVideoWidth(long j);
public static final native int _isLooping(long j);
public static final native int _isPlaying(long j);
public static final native int _pause(long j);
public static final native int _prepare(long j);
public static final native void _release(long j);
public static final native int _reset(long j);
public static final native int _seek(long j, int i);
public static final native void _setCacheFile(long j, String str, int i);
public static final native void _setDataSource(long j, String str);
public static final native void _setDataSourceFd(long j, int i);
public static final native int _setFloatValue(long j, int i, float f);
public static final native int _setIntValue(long j, int i, int i2);
public static final native int _setLongValue(long j, int i, long j2);
public static final native void _setLooping(long j, int i);
public static final native int _setStringValue(long j, int i, String str);
public static final native void _setSupprotSampleRates(int[] iArr, int i);
public static final native int _setVideoSurface(long j, Surface surface);
public static final native void _setVolume(long j, float f, float f2);
public static final native int _start(long j);
public static final native void _stop(long j);
正常包:
TTPlayer
类 Native
方法声明public static final native void _close(long j);
private final native long _create(Context context, int i, String str);
public static final native String _getAppPath();
public static final native int _getCurrentPosition(long j);
public static final native double _getDoubleValue(long j, int i, double d);
public static final native int _getDuration(long j);
public static final native float _getFloatValue(long j, int i, float f);
public static final native int _getIntValue(long j, int i, int i2);
public static final native Object _getJObjectValue(long j, int i);
public static final native long _getLongValue(long j, int i, long j2);
public static final native String _getStringValue(long j, int i);
public static final native int _getVideoHeight(long j);
public static final native int _getVideoWidth(long j);
public static final native int _isLooping(long j);
public static final native int _isPlaying(long j);
public static final native void _mouseEvent(long j, int i, int i2, int i3);
public static final native int _pause(long j);
public static final native int _prepare(long j);
public static final native void _prevClose(long j);
public static final native void _registerPlayerInfo();
public static final native void _release(long j);
public static final native int _reset(long j);
public static final native void _rotateCamera(long j, float f, float f2);
public static final native int _seek(long j, int i);
public static final native void _setAudioProcessor(long j, AudioProcessor audioProcessor);
public static final native void _setCacheFile(long j, String str, int i);
public static final native void _setDataSource(long j, IMediaDataSource iMediaDataSource);
public static final native void _setDataSource(long j, String str);
public static final native void _setDataSourceFd(long j, int i);
public static final native int _setDoubleValue(long j, int i, double d);
public static final native int _setFloatValue(long j, int i, float f);
public static final native int _setIntValue(long j, int i, int i2);
public static final native void _setLoadControl(long j, LoadControl loadControl);
public static final native int _setLongValue(long j, int i, long j2);
public static final native void _setLooping(long j, int i);
public static final native void _setMaskInfo(long j, MaskInfo maskInfo);
public static final native void _setMediaTransport(long j, MediaTransport mediaTransport);
public static final native int _setStringValue(long j, int i, String str);
public static final native void _setSubInfo(long j, SubInfo subInfo);
public static final native void _setSupportFormatNB(int i);
public static final native void _setSupprotSampleRates(int[] iArr, int i);
public static final native int _setSurfaceValue(long j, long j2);
public static final native int _setVideoSurface(long j, Surface surface);
public static final native void _setVolume(long j, float f, float f2);
public static final native int _start(long j);
public static final native void _stop(long j);
public static final native void _switchStream(long j, int i, int i2);
public static final native void _takeScreenshot(long j);
上面两个都是该类下所有的前提是: 1、使用同一个工程打包 2、以上代码所依赖的是同一个版本的穿山甲广告 SDK 3、其中有一个模块版本不一样(作者自己的一个 library) 4、打的是 release 包native 方法
,肉眼可见崩溃包的 native 代码明显比正常包的少;
上文日志 1 中提到Failed to register native method com.bykv.vk.component.ttvideo.player.TTPlayer._close(J)V
;
查看崩溃包的 native 方法,果然没有此方法public static final native void _close(long j);
;
猜想: 如果是同一个版本的同一份代码,是否有可能是因为混淆规则不同,或者冲突导致无用代码被移除,最终造成 native 方法注册失败出现的崩溃?
那么接下来去看看打包输出的混淆相关文件如何:
mapping.txt:源代码混淆的映射表 seeds.txt:未被混淆的类和成员 dump.txt:所有代码被处理后的完整列表 usage.txt:被优化移除、删除的代码 【本文我们重点关注这个】3、混淆分析 我们针对
com.bykv.vk.component.ttvideo.player.TTPlayer._close(J)V
native 方法进行分析!!!方法原型是:
public static final native void _close(long j);
崩溃包
mapping.txt
没有发现 \_close(long j) 方法被混淆seeds.txt
没有发现 \_close(long j) 方法被保留usage.txt
发现
\_close(long j) 方法被移除
除此之外,我们还发现其他的 native 方法也被移除了!!! (上面有提到崩溃包的 native 方法比正常包的要少) 文章图片
正常包
mapping.txt
没有发现 \_close(long j) 方法被混淆seeds.txt
发现
\_close(long j) 方法被保留
usage.txt没有发现 \_close(long j) 方法被移除明显了,分析到这里看到了两个包混淆之间的差别:大胆猜测是 native 方法没有找到,引起注册失败,导致崩溃。
有一点总结:native 方法不能被混淆、移除。
4、最后 那么,在我的项目中如何处理就比较清楚了,添加混淆规则,不移除、不会混淆该 native 方法即可。
-keep class com.bykv.vk.** {*;
}
-keepclasseswithmembernames class * {
native ;
}
-keepclassmembers class com.bykv.vk.component.ttvideo.player.TTPlayer {
*;
}
推荐阅读
- android 推断手机是否支持前置摄像头
- Android 跨进程调用忽略权限
- 一分钟了解Android横竖屏 mdpi hdpi xhdpi xxhdpi xxxhdpi
- android三种加载图片方式
- Android -Services 使用简介
- Android适配不同的设备
- 泛泰A820L (高通MSM8660 cpu)3.4内核的CM10.1(Android 4.2.2) 測试版第二版
- 挨踢部落故事汇(20):Android程序员的十大转型之路
- Android 下实现通用自启动守护实现