[解BUG系列]一个奇怪的问题

1,542 阅读3分钟

youtube(2.10.13)在Android TV上运行的时候,概率性出现crash,crash多发生在上电开机或首次打开的时候。

--------- beginning of crash
06-02 12:13:33.335  4072  4072 E AndroidRuntime: FATAL EXCEPTION: main
06-02 12:13:33.335  4072  4072 E AndroidRuntime: Process: com.google.android.youtube.tv.recommendations, PID: 4072
06-02 12:13:33.335  4072  4072 E AndroidRuntime: java.lang.RuntimeException: Unable to create application com.google.android.apps.youtube.tv.application.TvApplication: java.lang.IllegalStateException: WorkManager is not initialized properly.  You have explicitly disabled WorkManagerInitializer in your manifest, have not manually called WorkManager#initialize at this point, and your Application does not implement Configuration.Provider.
06-02 12:13:33.335  4072  4072 E AndroidRuntime:        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5384)
06-02 12:13:33.335  4072  4072 E AndroidRuntime:        at android.app.ActivityThread.-wrap2(ActivityThread.java)
06-02 12:13:33.335  4072  4072 E AndroidRuntime:        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1528)
06-02 12:13:33.335  4072  4072 E AndroidRuntime:        at android.os.Handler.dispatchMessage(Handler.java:102)
06-02 12:13:33.335  4072  4072 E AndroidRuntime:        at android.os.Looper.loop(Looper.java:154)
06-02 12:13:33.335  4072  4072 E AndroidRuntime:        at android.app.ActivityThread.main(ActivityThread.java:6097)
06-02 12:13:33.335  4072  4072 E AndroidRuntime:        at java.lang.reflect.Method.invoke(Native Method)
06-02 12:13:33.335  4072  4072 E AndroidRuntime:        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1052)
06-02 12:13:33.335  4072  4072 E AndroidRuntime:        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:942)
06-02 12:13:33.335  4072  4072 E AndroidRuntime: Caused by: java.lang.IllegalStateException: WorkManager is not initialized properly.  You have explicitly disabled WorkManagerInitializer in your manifest, have not manually called WorkManager#initialize at this point, and your Application does not implement Configuration.Provider.
06-02 12:13:33.335  4072  4072 E AndroidRuntime:        at ww.a(PG:29)
06-02 12:13:33.335  4072  4072 E AndroidRuntime:        at bqz.a(PG:3)
06-02 12:13:33.335  4072  4072 E AndroidRuntime:        at foc.a(PG:4)
06-02 12:13:33.335  4072  4072 E AndroidRuntime:        at bqw.a(PG:17)
06-02 12:13:33.335  4072  4072 E AndroidRuntime:        at cof.a(PG:20)
06-02 12:13:33.335  4072  4072 E AndroidRuntime:        at cof.a(PG:18)
06-02 12:13:33.335  4072  4072 E AndroidRuntime:        at com.google.android.apps.youtube.tv.application.TvApplication.onCreate(PG:32)
06-02 12:13:33.335  4072  4072 E AndroidRuntime:        at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1024)
06-02 12:13:33.335  4072  4072 E AndroidRuntime:        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5381)
06-02 12:13:33.335  4072  4072 E AndroidRuntime:        ... 8 more

从日志来看,可以有以下发现:

  • 程序运行过程中发生了异常Exception,并且异常发生在youtube APP内部。onCreate(PG:32)开始的行知道抛出异常的地方都在应用内部。
  • 异常产生的原因是:WorkManager没有进行合适的初始化。
  • 应用内部没有捕获异常,直接进入Android默认的异常处理流程:杀死进程,并打印堆栈信息。

Youtube App是Google开发的,Android OS也是谷歌开发的,正常情况下,从哪个角度看,这个问题都应该是Google来分析解决。无奈存在一种不正常的情况,就是Android系统没有进行Google授权认证的情况下,出现的一概问题官方都不负责。这个问题也不排除是系统整合没有遵从Google的相关规定,但是这个规定有点多而且有些还很隐晦,靠猜是很难办的。

从APP开始分析

问题发生在应用内部,一般情况下都是先从应用分析。Youtube APP闭源,所以要采取一些非常规的手段,比如反编译。现在各种防止反编译的手段非常多,使用常规的工具几乎不可能,有条件的可以使用专业工具。下面是使用常规工具,反编译失败:

$ ./d2j-dex2jar.sh ../../tmp/classes.dex 
dex2jar ../../tmp/classes.dex -> ./classes-dex2jar.jar
Detail Error Information in File ./classes-error.zip
Please report this file to http://code.google.com/p/dex2jar/issues/entry if possible.

系统层打补丁(下下策)

有的时候,不得不采取一些非常规的手段。比如这题APP端无法分析,可以换个角度,从crash堆栈分析,Android Framework层捕获APP抛出的异常,然后抛出一个新异常,这个新异常导致crash。所以,可以尝试把Framework抛出异常的地方进行一点小小的处理,比如针对本题的错误,不抛出异常,看APP的行为是否正常。

frameworks/base/core/java/android/app/ActivityThread.java

                 mInstrumentation.callApplicationOnCreate(app);
             } catch (Exception e) {
                 if (!mInstrumentation.onException(app, e)) {
-                    throw new RuntimeException(
-                        "Unable to create application " + app.getClass().getName()
-                        + ": " + e.toString(), e);
+                    if(app.getClass().getName().contains("youtube") && e.toString().contains("WorkManager is not initialized")){
+                        Slog.w("DSTTT", "skip youtube recommendations error!!!");
+                    }
+                    else {
+                        throw new RuntimeException(
+                            "Unable to create application " + app.getClass().getName()
+                            + ": " + e.toString(), e);
+                    }
                 }
             }
         } finally {

LUCKY,运行正常,用户不会体验到任何异常!

此乃非常规手段,谨慎使用!