概述
背景:
上周遇到一些无法开机的机器,都是卡在开机动画,很是头疼,基本上可以定位到是data分区里的文件出了问题,但是很难进一步分析,只有一点点去看这些文件,做下总结。
分析:
具体可以分成两种情况:
1、其中一种是报无法找到android这个包名无法找到:
android.content.pm.PackageManager$NameNotFoundException: android
01-02 01:34:11.010 I/SystemServer( 1059): User Service
01-02 01:34:11.019 E/System ( 1059): ******************************************
01-02 01:34:11.019 E/System ( 1059): ************ Failure starting system services
01-02 01:34:11.019 E/System ( 1059): java.lang.RuntimeException: Unable to find android system package
01-02 01:34:11.019 E/System ( 1059): at com.android.server.am.ActivityManagerService.setSystemProcess(ActivityManagerService.java:2399)
01-02 01:34:11.019 E/System ( 1059): at com.android.server.SystemServer.startBootstrapServices(SystemServer.java:533)
01-02 01:34:11.019 E/System ( 1059): at com.android.server.SystemServer.run(SystemServer.java:355)
01-02 01:34:11.019 E/System ( 1059): at com.android.server.SystemServer.main(SystemServer.java:242)
01-02 01:34:11.019 E/System ( 1059): at java.lang.reflect.Method.invoke(Native Method)
01-02 01:34:11.019 E/System ( 1059): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:888)
01-02 01:34:11.019 E/System ( 1059): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:749)
01-02 01:34:11.019 E/System ( 1059): Caused by: android.content.pm.PackageManager$NameNotFoundException: android
01-02 01:34:11.019 E/System ( 1059): at android.app.ApplicationPackageManager.getApplicationInfo(ApplicationPackageManager.java:312)
01-02 01:34:11.019 E/System ( 1059): at com.android.server.am.ActivityManagerService.setSystemProcess(ActivityManagerService.java:2374)
01-02 01:34:11.019 E/System ( 1059): ... 6 more
这就奇怪了,因为我们都知道android这个包就是framework-res.apk,在/system/app/下都能看到,MD5也是对的,看了下package.list,package.xml也都没问题。
只能把文件拷贝出来一个一个看了,最后发现是/data/system/users/userlist.xml这个文件出了问题。
原本文件是:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<users nextSerialNumber="10" version="4">
<user id="0" />
</users>
但是出问题的盒子<user id="0" />
这一行直接没了,导致系统根本都没用户了,所以才一直找不到framework-res.apk。
这个问题在网上看到有人类似的是data/system/users/0/package-restrictions.xml文件产生了异常。解决方法都是将其删掉重启就可以了。
2、第二种情况和odex有关,这个就比较好定位了,把/data/dalvik-cache/下的文件拿出来和正常的文件对比,确实发现有些文件损坏了(数据丢失)。
如何确定odex文件是不是被破坏了呢?可以使用android的dexdump命令来验证,如果该命令可以解析,说明odex文件是ok的,否则是被破坏。
这种情况见过两种log,一种是:
E/dalvikvm( 9865): ERROR: Byte swap + verify failed
E/dalvikvm( 9865): Optimization failed
E/dalvikvm( 9864): Unable to extract+optimize DEX from '/system/framework/framework.jar'
E/dalvikvm( 9867): Out-of-order entry types: 0x581 then 0x581
E/dalvikvm( 9867): Trouble with item 328 @ offset 0x48750
E/dalvikvm( 9867): Cross-item verify of section type 1003 failed
E/dalvikvm( 9867): ERROR: Byte swap + verify failed
E/dalvikvm( 9867): Optimization failed
E/dalvikvm( 9864): Unable to extract+optimize DEX from '/system/framework/services.jar'
另一种是JNI注册发生一些错误,有时是类没找到,有时是注册时直接崩溃掉:
D/dalvikvm( 138): Trying to load lib libjavacore.so 0x0
D/dalvikvm( 138): Added shared lib libjavacore.so 0x0
D/dalvikvm( 138): Trying to load lib libnativehelper.so 0x0
D/dalvikvm( 138): Added shared lib libnativehelper.so 0x0
D/dalvikvm( 138): No JNI_OnLoad found in libnativehelper.so 0x0, skipping init
W/dalvikvm( 138): Recursive link on class ex
W/dalvikvm( 138): 035
W/dalvikvm( 138): Unable to resolve superclass of ex
W/dalvikvm( 138): 035 (5574)
W/dalvikvm( 138): Link of class 'Landroid/debug/JNITest;' failed
E/dalvikvm( 138): JNI posting fatal error: Native registration unable to find class 'android/debug/JNITest'; aborting...
I/dalvikvm( 138): "main" prio=5 tid=1 NATIVE
I/dalvikvm( 138): | group="main" sCount=0 dsCount=0 obj=0x4169dca8 self=0x415d6430
I/dalvikvm( 138): | sysTid=138 nice=0 sched=0/0 cgrp=default handle=1074393428
I/dalvikvm( 138): | state=R schedstat=( 365326000 113051000 369 ) utm=27 stm=9 core=2
I/dalvikvm( 138): #00 pc 0000132e /system/lib/libcorkscrew.so (unwind_backtrace_thread+29)
I/dalvikvm( 138): #01 pc 00060652 /system/lib/libdvm.so (dvmDumpNativeStack(DebugOutputTarget const*, int)+33)
I/dalvikvm( 138): #02 pc 00054640 /system/lib/libdvm.so (dvmDumpThreadEx(DebugOutputTarget const*, Thread*, bool)+395)
I/dalvikvm( 138): #03 pc 000546ae /system/lib/libdvm.so (dvmDumpThread(Thread*, bool)+25)
I/dalvikvm( 138): #04 pc 000490c0 /system/lib/libdvm.so
I/dalvikvm( 138): #05 pc 00001fa8 /system/lib/libnativehelper.so (jniRegisterNativeMethods+39)
I/dalvikvm( 138): #06 pc 0004d922 /system/lib/libandroid_runtime.so
I/dalvikvm( 138): #07 pc 0004dc10 /system/lib/libandroid_runtime.so (android::AndroidRuntime::startReg(_JNIEnv*)+23)
I/dalvikvm( 138): #08 pc 0004e660 /system/lib/libandroid_runtime.so (android::AndroidRuntime::start(char const*, char const*)+183)
I/dalvikvm( 138): #09 pc 0000105a /system/bin/app_process
I/dalvikvm( 138): #10 pc 0000e988 /system/lib/libc.so (__libc_init+100)
I/dalvikvm( 138): at dalvik.system.NativeStart.main(Native Method)
I/dalvikvm( 138): at dalvik.system.NativeStart.main(Native Method)
I/dalvikvm( 138):
E/dalvikvm( 138): VM aborting
F/libc ( 138): Fatal signal 6 (SIGABRT) at 0x0000008a (code=-6), thread 138 (zygote)
I/DEBUG ( 136): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG ( 136): Build fingerprint: 'Sumavision/S6/RAM:1G/ROM:4G'
I/DEBUG ( 136): Revision: '10'
I/DEBUG ( 136):
I/DEBUG ( 136):
I/DEBUG ( 136): Crash Time:----- 1970-11-06-19-34 -----
I/DEBUG ( 136): pid: 138, tid: 138, name: zygote >>> zygote <<<
I/DEBUG ( 136): signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
I/DEBUG ( 136): r0 00000000 r1 0000008a r2 00000006 r3 00000000
I/DEBUG ( 136): r4 00000006 r5 00000002 r6 0000008a r7 0000010c
I/DEBUG ( 136): r8 00000004 r9 beffbbe3 sl 00000000 fp beffbbc2
I/DEBUG ( 136): ip 40234480 sp beffb668 lr 400cb1a1 pc 400da174 cpsr 000f0010
I/DEBUG ( 136): d0 74726f6261204d56 d1 614e2e6d65747379
I/DEBUG ( 136): d2 65747379732f2020 d3 696c2f62696c2f6d
I/DEBUG ( 136): d4 64696f72646e6162 d5 656d69746e75725f
I/DEBUG ( 136): d6 646e6128206f732e d7 6e413a3a64696f72
规避方法:
针对上面的这两种情况,相同的都会影响zygote进程。在android的原生代码中,对于zygote开机故障是有一些恢复措施的。 那就是dalvik_recache机制。以下是dalvik_recache源码中的介绍,其中我们可以看到,dalvik_recache只能对zygote进程生效:
dalvik_recache Currently, this is designed for zygote only, zygote is
crashed(cause by damaged dex files in /data/dalvik-cache/ ) at boot time, and this option is set, it will clean all dex files. Don`t
use with critical
Zygote进程在init.rc中被声明为Service并由Init进程创建。当Zygote进程退出时,将向Init进程发送SIGCHLD信号。前面的代码已经完成了信号的初始化操作,所以当信号到来时会调用SIGCHLD_handler()函数处理,它的处理就是直接通过socket写入一个数据就立刻返回;这时,SIGCHLD的处理就转移到socket事件的响应上。我们通过epoll_ctl注册了本地socket,并监听它是否可读;这时由于之前的write()调用,此时socket有数据可读,此刻会调用注册的handle_signal()函数进行处理:
void handle_signal(void)
{
char tmp[32];
/* we got a SIGCHLD - reap and restart as needed */
read(signal_recv_fd, tmp, sizeof(tmp));
while (!wait_for_one_process(0))
;
}
而handle_signal最终会调用到wait_for_one_process函数。
其中我们截取和故障处理相关的片段:
if ((svc->flags & SVC_ONESHOT) && !(svc->flags & SVC_RESTART)) {
svc->flags |= SVC_DISABLED;
}
/* disabled and reset processes do not get restarted automatically */
if (svc->flags & (SVC_DISABLED | SVC_RESET) ) {
notify_service_state(svc->name, "stopped");
return 0;
}
now = gettime();
if ((svc->flags & SVC_CRITICAL) && !(svc->flags & SVC_RESTART)) {
if (svc->time_crashed + CRITICAL_CRASH_WINDOW >= now) {
if (++svc->nr_crashed > CRITICAL_CRASH_THRESHOLD) {
ERROR("critical process '%s' exited %d times in %d minutes; "
"rebooting into recovery moden", svc->name,
CRITICAL_CRASH_THRESHOLD, CRITICAL_CRASH_WINDOW / 60);
android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
return 0;
}
} else {
svc->time_crashed = now;
svc->nr_crashed = 1;
}
}else if (svc->flags & SVC_DALVIK_RECACHE) {
if (svc->time_started + RECACHE_ENABLE_PHASE >= now) {
ERROR("recacheabl process '%s' exited at(%lu) ,start(%lu)",
svc->name, now, svc->time_started);
system("/system/xbin/busybox rm /data/dalvik-cache/*");
}
}
如果添加了该标志(SVC_DALVIK_RECACHE),也就是init.rc zygote的service要添加dalvik_recache,如果zygote崩溃时间超过5分钟,则会删掉/data/dalvik-cache/*,这样系统会重新优化dex文件。同样的,我们可以把其他出错文件的删除也添加到这里,这样就会做类似处理。之前说的两种故障,都可以用该方法规避。
另外我们也看到这段代码中对于其他标志的处理方式:
1、如果该服务进程带有SVC_ONESHOT标志,且没有SVC_RESTART标志,则表明该服务无需重启 ;
2、如果服务带有SVC_RESET标志,表示服务无需重启;
3、如果一个服务进程带有SVC_CRITICAL标志,且没有SVC_RESTART标志,当它crash时间超过4分钟且重启的次数超过4此时,系统会自动重启并进入recovery模式;
最后关于class;dex;odex,可以参考:
http://blog.csdn.net/Innost/article/details/50377905
最后
以上就是老实薯片为你收集整理的Android 故障 开机无法启动的全部内容,希望文章能够帮你解决Android 故障 开机无法启动所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复