抖音BoostMultiDex优化实践:Android低版本上APP首次启动时间减少80%(二)(1)

#06 pc 0002b5c4 /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184) [armeabi-v7a]

#07 pc 0005fc79 /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+272) [armeabi-v7a]

#08 pc 0005fca3 /system/lib/libdvm.so (dvmCallMethod(Thread*, Method const*, Object*, JValue*, …)+20) [armeabi-v7a]

#09 pc 0005481f /system/lib/libdvm.so [armeabi-v7a]

#10 pc 0000e3e8 /system/lib/libc.so (__thread_entry+72) [armeabi-v7a]

#11 pc 0000dad4 /system/lib/libc.so (pthread_create+160) [armeabi-v7a]

APP 收到 SIGSTKFLT 信号崩溃了,同时还输出了这样的日志:

06-25 15:10:53.821 7449 7450 E dalvikvm: threadid=2: stuck on threadid=135, giving up

06-25 15:10:53.821 7449 7450 D dalvikvm: threadid=2: sending two SIGSTKFLTs to threadid=135 (tid=8021) to cause debuggerd dump

SIGSTKFLT 是 Dalvik 虚拟机特有的一个信号。当虚拟机发生了 ANR 或者需要做 GC 的时候,就需要挂起所有 RUNNING 状态的线程,如果此时 Dalvik 虚拟机等待了足够长时间,线程仍旧无法被挂起,就会调用dvmNukeThread函数发送 SIGSTKFLT 信号给相应线程,从而杀死 APP。

具体代码如下:

static void waitForThreadSuspend(Thread* self, Thread* thread)

{

const int kMaxRetries = 10;

… …

while (thread->status == THREAD_RUNNING) {

… …

if (retryCount++ == kMaxRetries) {

ALOGE(“Fatal spin-on-suspend, dumping threads”);

dvmDumpAllThreads(false);

/* log this after – long traces will scroll off log */

=> ALOGE(“threadid=%d: stuck on threadid=%d, giving up”,

self->threadId, thread->threadId);

/* try to get a debuggerd dump from the spinning thread */

=> dvmNukeThread(thread);

/* abort the VM */

dvmAbort();

… …

}

而从堆栈我们看出,杀死进程的时候,我们正调用DexFile.loadDex,这个方法最后会调用到dvmRawDexFileOpen里面,执行 write 操作。而这个 write 涉及 I/O 操作,是比较耗时的。所以,当线程在做 dexopt,长时间无法响应虚拟机的挂起请求时,就会触发这个问题。

一般来说,虚拟机在执行 Java 代码的时候,都会是 RUNNING 状态。而只要调用了 JNI 方法,在执行到 C/C++代码的时候,就会切换为 NATIVE 状态。而虚拟机只会在 RUNNING 状态下会挂起线程,如果是在 NATIVE 状态下,虚拟机是不会要求线程必须挂起的。

不过,这里有一个特殊之处。虽然DexFile.loadDex方法最终也走到了 JNI 里面调用dvmRawDexFileOpen函数,但由于DexFile类是虚拟机的内部类,Dalvik 虚拟机不会在内部类执行 JNI 方法的时候将线程切换为 NATIVE 状态,仍然会保持原来的 RUNNING 状态。于是,在 RUNNING 状态下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值