NoClassDefFoundError

来源:互联网 发布:计算机就业前景 知乎 编辑:程序博客网 时间:2024/05/20 09:27

1.       Background

1.1     reproducibility

某个apk在androidO的一个分支上启动的时候出现FC

 

01-06 03:02:51.913 3980  3980 D AndroidRuntime:Shutting down VM

01-06 03:02:51.914 3980  3980 E AndroidRuntime: FATALEXCEPTION: main

01-06 03:02:51.914 3980  3980 E AndroidRuntime:Process: com.chinamworld.main, PID: 3980

01-06 03:02:51.914 3980  3980 E AndroidRuntime:java.lang.NoClassDefFoundError: Failed resolution of:Lcom/ccb/framework/util/CcbLogger;

01-06 03:02:51.914 3980  3980 E AndroidRuntime:           atcom.ccb.start.CcbSplashActivity.onCreateOrg(Unknown Source:14)

01-06 03:02:51.914 3980  3980 E AndroidRuntime:           atcom.ccb.start.CcbSplashActivity.onCreate(Unknown Source:0)

01-06 03:02:51.914 3980  3980 E AndroidRuntime:           at android.app.Activity.performCreate(Activity.java:6999)

01-06 03:02:51.914 3980  3980 E AndroidRuntime:           atandroid.app.Activity.performCreate(Activity.java:6990)

01-06 03:02:51.914 3980  3980 E AndroidRuntime:           atandroid.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1215)

01-06 03:02:51.914 3980  3980 E AndroidRuntime:           atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731)

01-06 03:02:51.914 3980  3980 E AndroidRuntime:           atandroid.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)

01-06 03:02:51.914 3980  3980 E AndroidRuntime:           atandroid.app.ActivityThread.-wrap11(Unknown Source:0)

01-06 03:02:51.914 3980  3980 E AndroidRuntime:           atandroid.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)

01-06 03:02:51.914 3980  3980 E AndroidRuntime:           atandroid.os.Handler.dispatchMessage(Handler.java:106)

01-06 03:02:51.914 3980  3980 E AndroidRuntime:           atandroid.os.Looper.loop(Looper.java:164)

01-06 03:02:51.914 3980  3980 E AndroidRuntime:           at android.app.ActivityThread.main(ActivityThread.java:6501)

01-06 03:02:51.914 3980  3980 E AndroidRuntime:           atjava.lang.reflect.Method.invoke(Native Method)

01-06 03:02:51.914 3980  3980 E AndroidRuntime:           atcom.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)

01-06 03:02:51.914 3980  3980 E AndroidRuntime:           atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

01-06 03:02:51.914 3980  3980 E AndroidRuntime:Caused by: java.lang.ClassNotFoundException: Didn't find class"com.ccb.framework.util.CcbLogger" on path: DexPathList[[zip file"/data/user/0/com.chinamworld.main/.cache/classes.jar", zip file"/data/app/com.chinamworld.main-sJGleomDgK0_gomW8ZFeTw==/base.apk"],nativeLibraryDirectories=[/data/app/com.chinamworld.main-sJGleomDgK0_gomW8ZFeTw==/lib/arm,/system/fake-libs,/data/app/com.chinamworld.main-sJGleomDgK0_gomW8ZFeTw==/base.apk!/lib/armeabi-v7a,/system/lib, /vendor/lib]]

01-06 03:02:51.914 3980  3980 E AndroidRuntime:           at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:125)

01-06 03:02:51.914 3980  3980 E AndroidRuntime:           atjava.lang.ClassLoader.loadClass(ClassLoader.java:379)

01-06 03:02:51.914 3980  3980 E AndroidRuntime:           atjava.lang.ClassLoader.loadClass(ClassLoader.java:312)

01-06 03:02:51.914 3980  3980 E AndroidRuntime:           ... 15 more

 

 

 

2.       Analysis

2.1          Step1:

2.1.1           Log1

 

01-0603:02:51.914  3980  3980 E AndroidRuntime:java.lang.NoClassDefFoundError: Failed resolution of:Lcom/ccb/framework/util/CcbLogger;

 

从log看,貌似是一个类加载器引起的命名空间问题。

 

一番分析加载路径,无果。

 

 

 

2.1.2           Log2

再仔细查看整个log,会发现下面一段

 

01-06 03:02:56.042 4034  4034 W zygote  : Opening an oat file without a class loader.Are you using the deprecated DexFile APIs?

01-06 03:02:56.056 4034  4034 W zygote  : Skipping duplicate class check due tounsupported classloader

01-06 03:02:56.059 4034  4034 W zygote  : Opening an oat file without a class loader.Are you using the deprecated DexFile APIs?

01-06 03:02:56.062 4034  4034 I System.out:java.io.IOException: No original dex files found for dex location/data/user/0/com.chinamworld.main/.cache/classes.jar

01-06 03:02:56.063 4034  4034 I System.out:        atdalvik.system.DexFile.openDexFileNative(Native Method)

01-06 03:02:56.063 4034  4034 I System.out:        atdalvik.system.DexFile.openDexFile(DexFile.java:353)

01-06 03:02:56.063 4034  4034 I System.out:        atdalvik.system.DexFile.<init>(DexFile.java:142)

01-06 03:02:56.063 4034  4034 I System.out:        atdalvik.system.DexFile.loadDex(DexFile.java:201)

01-06 03:02:56.063 4034  4034 I System.out:        atdalvik.system.DexPathList.loadDexFile(DexPathList.java:377)

01-06 03:02:56.063 4034  4034 I System.out:        atdalvik.system.DexPathList.makeDexElements(DexPathList.java:337)

01-06 03:02:56.063 4034  4034 I System.out:        atdalvik.system.DexPathList.makePathElements(DexPathList.java:423)

01-06 03:02:56.063 4034  4034 I System.out:        at java.lang.reflect.Method.invoke(NativeMethod)

01-06 03:02:56.063 4034  4034 I System.out:        atcom.secneo.apkwrapper.DexInstall$V19.makeDexElements(DexInstall.java:269)

01-06 03:02:56.063 4034  4034 I System.out:        at com.secneo.apkwrapper.DexInstall$V19.install(DexInstall.java:216)

01-06 03:02:56.063 4034  4034 I System.out:        atcom.secneo.apkwrapper.DexInstall$V19.access$100(DexInstall.java:201)

01-06 03:02:56.063 4034  4034 I System.out:        atcom.secneo.apkwrapper.DexInstall.installSecondaryDexes(DexInstall.java:67)

01-06 03:02:56.063 4034  4034 I System.out:        atcom.secneo.apkwrapper.DexInstall.install(DexInstall.java:32)

01-06 03:02:56.063 4034  4034 I System.out:        at java.lang.Runtime.nativeLoad(NativeMethod)

01-06 03:02:56.063 4034  4034 I System.out:        atjava.lang.Runtime.doLoad(Runtime.java:1099)

01-06 03:02:56.063 4034  4034 I System.out:        atjava.lang.Runtime.loadLibrary0(Runtime.java:1014)

01-06 03:02:56.064 4034  4034 I System.out:        at java.lang.System.loadLibrary(System.java:1657)

01-06 03:02:56.064 4034  4034 I System.out:        atcom.secneo.apkwrapper.ApplicationWrapper.<clinit>(ApplicationTemplate.java:27)

01-06 03:02:56.064 4034  4034 I System.out:        at java.lang.Class.newInstance(NativeMethod)

01-06 03:02:56.064  4034  4034 I System.out:      atandroid.app.Instrumentation.newApplication(Instrumentation.java:1103)

01-06 03:02:56.064 4034  4034 I System.out:      atandroid.app.Instrumentation.newApplication(Instrumentation.java:1088)

01-06 03:02:56.064 4034  4034 I System.out:        atandroid.app.LoadedApk.makeApplication(LoadedApk.java:983)

01-06 03:02:56.064 4034  4034 I System.out:        atandroid.app.ActivityThread.handleBindApplication(ActivityThread.java:5722)

01-06 03:02:56.064 4034  4034 I System.out:        at android.app.ActivityThread.-wrap1(UnknownSource:0)

01-06 03:02:56.064 4034  4034 I System.out:        atandroid.app.ActivityThread$H.handleMessage(ActivityThread.java:1656)

01-06 03:02:56.064 4034  4034 I System.out:        atandroid.os.Handler.dispatchMessage(Handler.java:106)

01-06 03:02:56.064 4034  4034 I System.out:        atandroid.os.Looper.loop(Looper.java:164)

01-06 03:02:56.064 4034  4034 I System.out:        atandroid.app.ActivityThread.main(ActivityThread.java:6501)

01-06 03:02:56.064 4034  4034 I System.out:        at java.lang.reflect.Method.invoke(NativeMethod)

 

 

从调用栈可以看出,这个是应用进程启动过程中,创建application的时候,加载了自定义的库文件,并且在该库文件中,用反射的方法加载multidex,最终由于在反射的时候使用了一个deprecatedDexFile API  makePathElements()实现自己的类加载器,这个api进一步调用了makeDexElements(List<File>files, File optimizedDirectory,

           List<IOException> suppressedExceptions, ClassLoader loader),传入的ClassLoader为null,在后面的OatFileManager::OpenDexFilesFromOat里面进行ClassLoader 检查的时候发现异常,导致加载dex失败,从而后续的类加载失败。

 

 

2.2          Step2:

2.2.1           Code

从最新代码开不出问题所在,比较出问题的代码分支,可以看出差异,

 

 

 



 

 


再结合类加载器的创建过程和application的调用栈,问题就很明显了。

 

 

2.2.2           代码文件名

 

oat_file_manager.cc

dalvik_system_DexFile.cc

BaseDexClassLoader.java

DexPathList.java

DexFile.java

 

 

 

 

 

3.       RootCause

这个是应用进程启动过程中,创建application的时候,加载了自定义的库文件,并且在该库文件中,用反射的方法加载multidex,最终由于在反射的时候使用了一个deprecatedDexFile API  makePathElements()实现自己的类加载器,这个api进一步调用了makeDexElements(List<File>files, File optimizedDirectory,

           List<IOException> suppressedExceptions, ClassLoader loader),传入的ClassLoader为null,在后面的OatFileManager::OpenDexFilesFromOat里面进行ClassLoader 检查的时候发现异常,导致加载dex失败,从而后续的类加载失败。

 

4.       Solution

4.1          Way 1  apk side

 

Apk should update it’s code by replacing the deprecatedDexFile API  makePathElements().

 

 

4.2          Way 2  AOSP side

The art should sync the code with the mainline

原创粉丝点击