01-01 12:00:00.869 1344 1344 E AndroidRuntime: FATAL EXCEPTION: main 01-01 12:00:00.869 1344 1344 E AndroidRuntime: Process: com.android.deskclock, PID: 1344 01-01 12:00:00.869 1344 1344 E AndroidRuntime: java.lang.RuntimeException: Unable to instantiate application com.android.deskclock.DeskClockApplication: java.lang.ClassNotFoundException: Didn't find class "com.android.deskclock.DeskClockApplication" on path: DexPathList[[zip file "/system/app/ApeDeskClock80/ApeDeskClock80.apk"],nativeLibraryDirectories=[/system/app/ApeDeskClock80/lib/arm64, /system/app/ApeDeskClock80/ApeDeskClock80.apk!/lib/armeabi, /system/lib, /vendor/lib, /system/lib, /vendor/lib]] 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at android.app.LoadedApk.makeApplication(LoadedApk.java:999) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5742) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at android.app.ActivityThread.-wrap1(Unknown Source:0) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1680) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:106) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at android.os.Looper.loop(Looper.java:164) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6523) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:857) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: Caused by: java.lang.ClassNotFoundException: Didn't find class "com.android.deskclock.DeskClockApplication" on path: DexPathList[[zip file "/system/app/ApeDeskClock80/ApeDeskClock80.apk"],nativeLibraryDirectories=[/system/app/ApeDeskClock80/lib/arm64, /system/app/ApeDeskClock80/ApeDeskClock80.apk!/lib/armeabi, /system/lib, /vendor/lib, /system/lib, /vendor/lib]] 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:125) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at java.lang.ClassLoader.loadClass(ClassLoader.java:379) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at java.lang.ClassLoader.loadClass(ClassLoader.java:312) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at android.app.Instrumentation.newApplication(Instrumentation.java:1087) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at android.app.LoadedApk.makeApplication(LoadedApk.java:993) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: ... 9 more 01-01 12:00:00.869 1344 1344 E AndroidRuntime: Suppressed: java.io.IOException: No original dex files found for dex location /system/app/ApeDeskClock80/ApeDeskClock80.apk 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at dalvik.system.DexFile.openDexFileNative(Native Method) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at dalvik.system.DexFile.openDexFile(DexFile.java:353) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at dalvik.system.DexFile.<init>(DexFile.java:100) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at dalvik.system.DexFile.<init>(DexFile.java:74) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at dalvik.system.DexPathList.loadDexFile(DexPathList.java:374) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at dalvik.system.DexPathList.makeDexElements(DexPathList.java:337) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at dalvik.system.DexPathList.<init>(DexPathList.java:157) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:65) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at dalvik.system.PathClassLoader.<init>(PathClassLoader.java:64) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at com.android.internal.os.ClassLoaderFactory.createClassLoader(ClassLoaderFactory.java:73) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at com.android.internal.os.ClassLoaderFactory.createClassLoader(ClassLoaderFactory.java:88) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at android.app.ApplicationLoaders.getClassLoader(ApplicationLoaders.java:69) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at android.app.ApplicationLoaders.getClassLoader(ApplicationLoaders.java:35) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at android.app.LoadedApk.createOrUpdateClassLoaderLocked(LoadedApk.java:703) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at android.app.LoadedApk.getClassLoader(LoadedApk.java:737) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at android.app.LoadedApk.getResources(LoadedApk.java:964) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at android.app.ContextImpl.createAppContext(ContextImpl.java:2271) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5666) 01-01 12:00:00.869 1344 1344 E AndroidRuntime: ... 8 more
…… 01-01 12:16:15.024 800 800 W PackageManager: Instruction set mismatch, PackageSetting{2aef961 com.ape.factory/1000} requires arm whereas PackageSetting{324db9c factory.tinnosnew.tinno.ui.test/1000} requires arm64 01-01 12:16:15.024 800 800 W PackageManager: Instruction set mismatch, PackageSetting{2aef961 com.ape.factory/1000} requires arm whereas PackageSetting{8fef249 com.android.settings/1000} requires arm64
问题原因都是同一个uid的app有的是32位的有的是64位的,uid都是1000 ,也就是是android.uid.system。从问题的现象可以推断该问题和第一次启动时的某些操作有关,另外和同uid的32位应用有关。根据这两篇博客在log中查找关键词Instruction set mismatch,找到32应用为com.ape.factory。问题点找到了,根据“Instruction set mismatch”的log可以追到PKMS中的adjustCpuAbisForSharedUserLPw方法,从方法名看是用来调整相同uid应用的cpuAbi的,那就来了解下ABI是什么,以及为什么会出现这个问题。
/** * Adjusts ABIs for a set of packages belonging to a shared user so that they all match. * i.e, so that all packages can be run inside a single process if required. * * Optionally, callers can pass in a parsed package via {@code newPackage} in which case * this function will either try and make the ABI for all packages in {@code packagesForUser} * match {@code scannedPackage} or will update the ABI of {@code scannedPackage} to match * the ABI selected for {@code packagesForUser}. This variant is used when installing or * updating a package that belongs to a shared user. * * NOTE: We currently only match for the primary CPU abi string. Matching the secondary * adds unnecessary complexity. */ privatevoidadjustCpuAbisForSharedUserLPw(Set<PackageSetting> packagesForUser, PackageParser.Package scannedPackage) {
PackageSettingrequirer=null;//首个能自身确定ABI的应用 //遍历同uid的应用,packagesForUser是个set,每次遍历的顺序不确定 for (PackageSetting ps : packagesForUser) { // If packagesForUser contains scannedPackage, we skip it. This will happen // when scannedPackage is an update of an existing package. Without this check, // we will never be able to change the ABI of any package belonging to a shared // user, even if it's compatible with other packages. if (scannedPackage == null || !scannedPackage.packageName.equals(ps.name)) { //找到首个能自身确定ABI的应用,用于确定requirer和requiredInstructionSet if (ps.primaryCpuAbiString == null) { continue; }
finalStringinstructionSet= VMRuntime.getInstructionSet(ps.primaryCpuAbiString); //找到首个能自身确定ABI的应用之前requiredInstructionSet一直为空 if (requiredInstructionSet != null && !instructionSet.equals(requiredInstructionSet)) { // We have a mismatch between instruction sets (say arm vs arm64) warn about // this but there's not much we can do. //同uid的应用是能运行在同一个进程的,所以指令集应该是一致的,但是如果不一致, //系统也无能为力 StringerrorMessage="Instruction set mismatch, " + ((requirer == null) ? "[caller]" : requirer) + " requires " + requiredInstructionSet + " whereas " + ps + " requires " + instructionSet; Slog.w(TAG, errorMessage); } //找到首个能自身确定ABI的应用后赋值,之后循环不会再走到这里 if (requiredInstructionSet == null) { requiredInstructionSet = instructionSet; requirer = ps; } } }
if (requiredInstructionSet != null) { String adjustedAbi; if (requirer != null) {//存在能确定自身ABI的应用 // requirer != null implies that either scannedPackage was null or that scannedPackage // did not require an ABI, in which case we have to adjust scannedPackage to match // the ABI of the set (which is the same as requirer's ABI) adjustedAbi = requirer.primaryCpuAbiString; if (scannedPackage != null) { scannedPackage.applicationInfo.primaryCpuAbi = adjustedAbi; } } else { // requirer == null implies that we're updating all ABIs in the set to // match scannedPackage. adjustedAbi = scannedPackage.applicationInfo.primaryCpuAbi; }
/** * The primary ABI that this application requires, This is inferred from the ABIs * of the native JNI libraries the application bundles. Will be {@code null} * if this application does not require any particular ABI. * * If non-null, the application will always be launched with this ABI. * * {@hide} */ public String primaryCpuAbi;