# GLThread 1371(29457) SIGSEGV(SEGV_MAPERR) #00 pc 0000000000aa3f58 /data/app/~~6_tV_wy5KiC1VMeFQPNi2g==/com.yddm.haiwai.game-bHeiJjIVfYMTmPlQwANbrw==/split_config.arm64_v8a.apk #01 pc 0000000000aafb84 /data/app/~~6_tV_wy5KiC1VMeFQPNi2g==/com.yddm.haiwai.game-bHeiJjIVfYMTmPlQwANbrw==/split_config.arm64_v8a.apk java: org.cocos2dx.lib.Cocos2dxRenderer.onDrawFrame(Cocos2dxRenderer.java:105) // 一个jni函数,调用到了c++,进行OpenGL相关的绘制 android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1593) android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1287)
有效的信息就这么多。
apk安装的细节
安卓系统已安装的软件会在/data/app目录内以base.apk形式存在
如果是通过google play安装的,aab的原因,apk会以split的形式存在
我在模拟器上验证了,从google play上下载的apk结构,apk大小还都不一样
perl
复制代码
star2qltechn:/data/app/com.romewargames.strategyempire-AGP1qpUXkGG3E_m0dBHR1A== # ls -ll total 408188 -rw-r--r-- 1 system system 8197841 2023-11-02 17:11:57.111427681 +0800 base.apk -rw-r--r-- 1 system system 12532 2023-11-02 17:13:35.134761014 +0800 base.dm drwxr-xr-x 3 system system 4096 2023-11-02 17:13:35.261427681 +0800 lib drwxrwx--x 3 system install 4096 2023-11-02 17:13:35.944761014 +0800 oat -rw-r--r-- 1 system system 355816799 2023-11-02 17:13:04.944761014 +0800 split_base_assets.apk -rw-r--r-- 1 system system 53932934 2023-11-02 17:13:30.771427681 +0800 split_config.arm64_v8a.apk
通过adb install,或者直接拖拽安装的,是以base.apk存在
perl
复制代码
star2qltechn:/data/app/free.v2ray.proxy.VPN-6RDmu-BT0ZNqmAZImYDKlA== # ls -ll total 14608 -rw-r--r-- 1 system system 14950019 2023-10-25 10:28:44.089183196 +0800 base.apk drwxr-xr-x 3 system system 4096 2023-10-25 10:28:44.175849863 +0800 lib drwxrwx--x 3 system install 4096 2023-10-25 10:28:45.615849863 +0800 oat
大小不太一致
从google play上安装的游戏,发现split_config.arm64_v8a.apk才34M,游戏整体大小是800多M,发现体积最大的是split_asset_pack.apk
yaml
复制代码
x1q:/data/app/com.yddm.haiwai.game-mbV5YOgNm4TcoRDp5ovYqg== # ls -ll total 906060 -rw-r--r-- 1 system system 49230425 2023-11-03 11:13:00.186139000 +0800 base.apk -rw-r--r-- 1 system system 20712 2023-11-03 11:13:07.536139000 +0800 base.dm drwxr-xr-x 3 system system 4096 2023-11-03 11:23:44.736139000 +0800 lib drwxrwx--x 3 system install 4096 2023-11-03 11:23:48.176139000 +0800 oat -rw-r--r-- 1 system system 842630903 2023-11-03 11:23:32.496139000 +0800 split_asset_pack.apk -rw-r--r-- 1 system system 35701753 2023-11-03 11:18:48.466139000 +0800 split_config.arm64_v8a.apk -rw-r--r-- 1 system system 33177 2023-11-03 11:13:20.846139000 +0800 split_config.en.apk -rw-r--r-- 1 system system 24985 2023-11-03 11:13:15.056139000 +0800 split_config.es.apk -rw-r--r-- 1 system system 85791 2023-11-03 11:12:13.916139000 +0800 split_config.xhdpi.apk -rw-r--r-- 1 system system 41369 2023-11-03 11:18:55.236139000 +0800 split_config.zh.apk
split_config.arm64_v8a.apk / Split APK
Android5.0引入了Split APK机制,Split APK是Google为解决65535上限以及APK越来越大的问题而提出的一种方案。
它可以将一个庞大的APK按照屏幕密度、ABI等形式拆分成多个独立的APK,这些APK共享相同的data、cache目录,共享相同的进程,共享相同的包名。
它们还可以使用各自的资源,并且继承了Base APK里的资源。相关的官方文档
Split APK机制可以将一个APK,拆分成多个独立APK。
在引入了Split APK机制后,APK有两种分类:
- Single APK:安装文件为一个完整的APK,即base APK。Android称其为Monolithic。
- Mutiple APK:安装文件在一个文件目录中,其内部有多个被拆分的APK,这些APK由一个 base APK和一个或多个split APK组成。Android称其为Cluster。
multiDexEnabled
在android5.0之前,每一个android应用中只会含有一个dex文件,但是这个dex的方法数量被限制在65535之内,这就是著名的64K(64*1024)事件。为了解决这个问题,Google官方推出了这个类似于补丁一样的support-library,MultiDex。
arduino 复制代码 android { compileSdkVersion 21 buildToolsVersion "21.1.0" defaultConfig { ... minSdkVersion 14 targetSdkVersion 21 ... // Enabling multidex support. multiDexEnabled true } ... } dependencies { compile 'com.android.support:multidex:1.0.0' }
xml 复制代码 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.android.multidex.myapplication"> <application ... android:name="android.support.multidex.MultiDexApplication"> ... </application> </manifest>
dalvik
Dalvik
是早期 Android 版本中用于运行安卓应用的虚拟机,由 Dan Bornstein
编写的,名字来源于他的祖先曾经居住过名叫 Dalvík 的小渔村,村子位于冰岛。
Dalvik 是解释执行加上 JIT,每次app运行的时候,它动态的将一部分 Dalvik 字节码
解释为机器码。随着 App 的运行,更多的字节码被编译和缓存。因为 JIT 只编译了一部分代码,它具有更小的内存占用和更少的设备物理空间占用。但是,边解释边执行,效率低下,这也是后来 Dalvik 遭到抛弃的原因。
从 Android 4.4 开始,Google 开始引入了全新的虚拟机 ART(Android Runtime)。ART 是基于 AOT 编译的,由于安装应用耗时过长,后期高版本的 Android 系统加入了加强版的 JIT 编译。Dalvik 在 Android 5.0 中正式被删除,ART 完成上位。
JIT (Just-In-Time - 实时编译) 和 AOT (Ahead-Of-Time - 预先编译)
ART 是向下兼容的,ART 和 Dalvik 是运行 Dex 字节码的兼容运行时,因此针对 Dalvik 开发的应用也能在 ART 环境中运作。不过,Dalvik 采用的一些技术并不适用于 ART。因此,Dalvik 虚拟机的部分特性以及 Dalvik 字节码指令其实和 ART 都是相通的。
/data/app目录
Android不同的目录存放不同类型的应用,如下所示:
- /system/framwork:保存的是资源型的应用程序,它们用来打包资源文件。
- /system/app:保存系统自带的应用程序。
- /data/app:保存用户安装的应用程序。
- /data/app-private:保存受DRM保护的私有应用程序。
- /vendor/app:保存设备厂商提供的应用程序。
获取abi
复制代码
adb shell getprop ro.product.cpu.abi
符号表
so里面有非常多的section,如果有.debug_xxx 的section一般都是带符号表的so,也就是debug的so,但是debug so里面也可以没有这些section,因为可以通过命令行工具把这部分section剥离掉。
一般我们说的符号表,不是什么特定的文件,指的就是.debug_xxx
之类的section,你可以把so的这部分section单独提取出来。
在 Android.mk 文件中启用符号表选项通常需要在 LOCAL_CFLAGS
和 LOCAL_LDFLAGS
中设置相应的选项。
以下是一个示例,它向您展示如何启用符号表选项:
makefile
复制代码
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := mylibrary LOCAL_SRC_FILES := mylibrary.c LOCAL_CFLAGS += -g LOCAL_LDFLAGS += -Wl,-Map=output.map -Wl,--cref include $(BUILD_SHARED_LIBRARY)
在上面的示例中,我们通过将 -g
添加到 LOCAL_CFLAGS
变量来启用调试符号选项。这会告诉编译器在生成目标文件时为其添加调试信息。
我们还使用 LOCAL_LDFLAGS
添加了两个链接标志:-Wl,-Map=output.map
和 -Wl,--cref
。这些选项告诉链接器在生成库文件时生成映射和交叉引用表。可以使用 ndk-build
命令构建您的项目,并找到生成的库文件及其相关符号表。
请注意,启用符号表选项可能会增加库文件的大小。因此,它们应该仅在调试过程中启用,并且在发布版本中应该禁用它们,以减小应用程序的体积。
readelf -S soFilePath
配合grep命令也能很快得到debug相关的信息
readelf 工具用于读取 ELF(可执行和可链接的格式)文件的信息。在调试版本的 NDK 库中,通常会包含以下重要的调试节区:
.debug_info
:这个节区包含了调试信息的核心部分,例如类型、变量、函数等的信息。它是调试器显示源代码和调试符号所需的主要节区之一。.debug_ranges
:这个节区包含了调试地址范围的信息。它指定了编译单元中代码的地址范围,用于在调试器中定位变量和函数的位置。.debug_str
:这个节区包含了调试信息中使用的字符串。它存储了类型和变量名称等字符串的实际文本。.debug_line
:这个节区包含了源代码行号和程序计数器(PC)之间的映射关系。它允许调试器在源代码级别上进行断点设置和单步执行。.debug_loc
:这个节区包含了局部变量和表达式的位置列表。它指定了变量在每个编译单元中的地址或地址范围。
这些节区的存在有助于调试器准确地映射源代码与机器代码之间的关系,并支持源代码级别的调试功能。
请注意,这只是对这些节区的简要解释,而实际的调试信息可能更加复杂和详细。对于更深入的了解,建议查阅相关文档或调试工具的说明。
排查mk为啥没导出符号信息
Android.mk就不用看了,重点排查app/jni/Application.mk,查看是否配置导出符号信息
makefile
复制代码 $(info $(NDK_DEBUG)) LOCAL_CFLAGS += -g LOCAL_CPPFLAGS += -g
这个task就是去除so符号表的任务,所以导致你怎么设置,最后apk里面的so都是没有符号表的
修改Android.mk,在build的android{}里面添加:
arduino 复制代码 packagingOptions { doNotStrip "*/armeabi-v7a/*.so" }
而带符号表的so的位置在:app\build\intermediates\ndkBuild\debug\obj\local\arm64-v8a
一般我们的都是使用这个进行调试。
java 复制代码 public class Cocos2dxRenderer implements GLSurfaceView.Renderer { // GLSurfaceView.Renderer是Android中用于渲染OpenGL ES图形的接口。 // 其中的onDrawFrame方法在每次绘制画面时被调用,它包含了一些必要的操作,以保证渲染的正确性和流畅性。 @Override public void onDrawFrame(final GL10 gl) { /* * No need to use algorithm in default(60 FPS) situation, * since onDrawFrame() was called by system 60 times per second by default. */ if (Cocos2dxRenderer.sAnimationInterval <= 1.0 / 60 * Cocos2dxRenderer.NANOSECONDSPERSECOND) { Cocos2dxRenderer.nativeRender(); } else { final long now = System.nanoTime(); final long interval = now - this.mLastTickInNanoSeconds; if (interval < Cocos2dxRenderer.sAnimationInterval) { try { Thread.sleep((Cocos2dxRenderer.sAnimationInterval - interval) / Cocos2dxRenderer.NANOSECONDSPERMICROSECOND); } catch (final Exception e) { } } /* * Render time MUST be counted in, or the FPS will slower than appointed. */ this.mLastTickInNanoSeconds = System.nanoTime(); Cocos2dxRenderer.nativeRender(); // 105在这里 } } }
c++ 复制代码 JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeRender(JNIEnv* env) { cocos2d::Director::getInstance()->mainLoop(); // 调用到了engine的mainloop }
pause resume
怀疑是这个导致的,这个操作距离用户崩溃非常近,有可能是sdk导致的,需要写个demo验证下,频繁的触发Activity观察是否能复现
怎么触发?
error1
typescript 复制代码 D/cocos2d-x debug info: [LUA-print] [string "app/util/Common.luac"]:1541: invalid 'cobj' in function 'lua_cocos2dx_RenderTexture_begin' stack traceback: [string "app/util/Common.luac"]:1541: in function <[string "app/util/Common.luac"]:1532>
audio
yaml 复制代码 AudioMixerController More than 8 active tracks: 18 AudioMixerController More than 8 active tracks: 17 AudioMixerController More than 8 active tracks: 17 assets/res/audio/sound/fight_die_blast.mp3 assets/res/audio/sound/env_day_land_atm_2.mp3
其他崩溃解决方案
firebase.google.cn/docs/crashl…
developer.android.google.cn/topic/perfo…
截屏