Android错误:随机出现java.lang.NoClassDefFoundError: com.facebook.internal.Utility。

14
我正在使用最新的Facebook Android SDK,在我的最新发布的apk中,远程崩溃控制应用程序中有数十个用户报告了该错误。我在这里查找了此类错误,但大多数答案对于最新的FB SDK来说都过时了,在这种情况下,有两个奇怪的情况:
a)错误似乎是随机发生的。我无法在任何设备上重现它。
b)在该版本和上一版本之间,FB逻辑没有任何变化,并且在以前的版本中,我从未遇到过这样的错误。
由于我无法在这些版本之间找到任何相关的代码区别,我认为问题可能是在生成最后一个apk时Android工具出了问题,但考虑到我正在使用的完全相同的apk,而且尽管有数十个用户受到影响,但使用相同apk的数百个用户没有受到影响,所以我也排除了这种假设。
欢迎提出任何解决或调试此问题的想法。
更多可能相关的信息:
- 所有崩溃都发生在Android 4.0.3或更早版本中。48%的崩溃发生在2.3.6上。 - 该类实际上在APK中被导出。我通过解压apk并使用dexdump来查看classes.dex中的内容进行了检查。我不会期望其他事情,因为它在我的所有设备上都可以完美地工作,如果该类不存在,则无法工作。 - 它似乎是在loadAppSettingsAsync调用Utility的静态方法后失败的,后者恰好是同一类中的一个静态方法。因此,如果com.facebook.internal.Utility类不存在或无法加载,那么如何可能在第一次执行com.facebook.internal.Utility.loadAppSettingsAsync时呢?如果它存在并已加载,为什么会抛出NoClassDefFoundError com.facebook.internal.Utility?我* 有点迷失......
这里是Splunk Mint(以前被称为bugsense)的堆栈,我只更改了应用程序的名称。我使用proguard映射文件重新跟踪了它,但似乎还是错过了一些行号:
java.lang.NoClassDefFoundError: com.facebook.internal.Utility$1
    at com.facebook.internal.Utility.void loadAppSettingsAsync(android.content.Context,java.lang.String)(Unknown Source)
    at com.facebook.Settings.void sdkInitialize(android.content.Context)(Unknown Source)
    at com.facebook.UiLifecycleHelper.<init>(Unknown Source)
    at net.iberdroid.androidgames.framework.impl.AndroidGame.void onCreate(android.os.Bundle)(Unknown Source)
    at com.marzoa.ruletafree.xmas2012.RuletaAfortunadaGame.void onCreate(android.os.Bundle)(Unknown Source)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1050)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1623)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1675)
    at android.app.ActivityThread.access$1500(ActivityThread.java:121)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:943)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:130)
    at android.app.ActivityThread.main(ActivityThread.java:3770)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:507)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:670)
    at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ClassNotFoundException: com.facebook.internal.Utility$1 in loader dalvik.system.PathClassLoader[/data/app/com.marzoa.ruletafree.xmas2012-2.apk]
    at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:240)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:551)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
    ... 18 more

你正在使用什么Proguard配置来处理Facebook类? - Ming Li
-keep class com.facebook.** { *; } -keepattributes Signature - Fran Marzoa
2个回答

5
在loadAppSettingsAsync中,由于AsyncTask的匿名实现而导致NoClassDefFoundError错误发生,似乎与此问题相同NoClassDefFoundError - Android 2.3.X
这是Google Play服务中的一个错误https://code.google.com/p/android/issues/detail?id=81083
尝试按照所引用问题的答案,在您的Application#onCreate()方法中添加以下内容。请注意保留HTML标签。
try {
    Class.forName("android.os.AsyncTask");
}
catch(Throwable ignore) {
    // ignored
}

这似乎有些道理。让我尝试发布一个新版本,带有该解决方法,看看会发生什么。不过,这样做会有副作用吗?我的意思是,忽略异常并不会改变需要这样的类而且它无法被下载的事实... - Fran Marzoa
1
不应该有任何副作用。这个解决方法只是确保类加载器将这个类显式地加载到内存中,以避免Play服务的错误。AsyncTask是Android系统的一个组件,肯定在每个设备上都可用。 - Udo
你好,我因为FacebookSdk遇到了问题。我应该怎么做才能解决这个问题?我已经尝试了上述方法,但它并没有起作用。 - Shreyash Mahajan
@Fran 你好,结果怎么样了?你修复好了吗?我遇到了同样的问题,因为找不到AsyncTask,所以我认为可能不是"Udo"所说的那种情况。 - Michael
我在哪里可以找到Application#onCreate()这个方法? - S. M. Asif

3
首先,请确保您正在检查正确的类。根据错误消息,"missing"类是com.facebook.internal.loadAppSettingsAsync$1。请注意$1!这意味着我们正在讨论在Utility.loadAppSettingsAsync内声明的匿名内部类。
其次,java.lang.NoClassDefFoundError可能有多种原因:
- 该类可能丢失了。 - 该类可能存在,但由于某种原因无法卸载 - 该类可能可以加载,但先前尝试初始化它或某个相关类时失败。
如果静态初始化程序或静态初始化块在第一次运行时引发未经检查的异常,则通常会出现最后一种情况。 (您通常会为此异常收到日志消息。)一旦类初始化失败,该类将被标记为损坏。 这将阻止该类及其依赖项的任何其他类进行初始化。

实际上那不是“缺失”的类,而是com.facebook.internal.Utility$1,我确定已经检查过它了(我已经编辑了问题并添加了一个带有grep的dexdump结果)。 - Fran Marzoa
就我所能重现的崩溃情况而言,无论类无法加载的原因是什么,都超出了我的调试器的范畴。我也没有远程访问用户日志的权限... :-| - Fran Marzoa
其实我有一部比我祖父还老的 Galaxy Y,但它从未出过故障。不管是那部手机还是我运行的所有模拟器都没有出现过问题。另一方面,我不会收集用户信息,所以我无法将崩溃与特定用户关联,以便联系他/她。无论如何,我现在正在查看该库的代码。 - Fran Marzoa
在“截至目前我已经能够重现崩溃”之前的部分,实际上应该是“截至目前我还没有能够重现崩溃”,尽管我认为由于上下文很清楚。 - Fran Marzoa
你说“一旦类初始化失败,该类就会被标记为损坏。”我能在代码中检查这种情况吗?我认为我可以将这些信息与堆栈转储一起添加到我的bugsense报告中。 - Fran Marzoa
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接