1

这个问题就像一个逻辑难题。你被警告了。

我正在开发一个与其他应用程序集成的库。一个人抱怨说,他们只看到部分用户崩溃:

java.lang.NoClassDefFoundError: com.somecompany.subpackage.SomeAsyncTaskSubclass
at com.somecompany.subpackage.ClassA.instantiateInstanceOfSomeAsyncTaskSubclass(ClassA.java:105)
at
com.somecompany.subpackage.Blah.loadsomedata(MyController.java:180)
at com.somecompany.subpackage.Blah.loadsomemoredata(MyController.java:164)
at com.somecompany.subpackage.SomeView.loadsomemoredata(SomeView.java:213)
com.other.blah.Blah.preloadstuff(Blah.java:118)
at
com.other.blah.Controller.loadSomething(Controller.java:100)
at
com.other.blah.Controller.preloadSomething(Controller.java:144)
at org.cocos2dx.lib.Cocos2dxRenderer.nativeRender(Native Method)
at org.cocos2dx.lib.Cocos2dxRenderer.onDrawFrame(Cocos2dxRenderer.java:94)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1332)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1116)

发生崩溃的代码行是:

public class ClassA {
    public void instantiateInstanceOfSomeAsyncTaskSubclass(){
        SomeAsyncTaskSubclass crashHere = new SomeAsyncTaskSubclass(); //<--- this is where it crashes
    }
}

在同一个包中,有...

class SomeAsyncTaskSubclass extends AsyncTask<String, Void, SomeCustomObject> {
// some code here...
}

这是我被告知或我知道的:

  1. 此崩溃仅发生在某些用户身上。(但基于 Google Play 崩溃报告。这是不准确的吗?还是样本生成速度太慢?)

  2. 即使使用签名版本,开发人员也无法在内部重现此错误。(我已经检查了签名的构建并对其进行了索引,以查看该类存在于 src 中,所以我相信他)

  3. 但是当应用程序在 Play 商店上线时,人们下载了他的新版本,他突然看到一些人的崩溃报告,据信主要是设备 2.3.x,尽管这未经证实)

  4. 他声称他已更新为“api 17”。当人们这么说时,他们的意思是构建目标 17 吗?还是人们的意思是更新到 ADT 17?因为我知道 ADT 解决了 lib/libs 文件夹问题。

  5. 他似乎正在使用日食。

  6. 他从 cocos2d-x for Android 调用我的代码,通过执行handler.post()

这怎么可能?

我很困惑为什么只有一些用户看到NoClassDefFoundError?这是一个巨大的谷歌播放崩溃报告问题吗?就像,所有用户都看到了它,但是谷歌播放说只有一些用户看到了这个问题?(我尚未与开发人员核实,但我相当确定他通过从 Play 商店下载实时版本进行了测试,并且他没有看到任何错误,并且那段代码运行良好)。

据我了解,NoClassDefFoundError只有当类通过三个类加载器之一存在时,但在运行时,没有一个类加载器可以找到特定的类。

这是一个proguard问题吗?我读过 proguard 只在发布时运行。

这是 AsyncTask 问题吗?我读过 AsyncTasks 必须第一次在 UI 线程上实例化。虽然,我不确定为什么会导致NoClassDefFoundError.

有什么想法吗?

4

3 回答 3

1

您的应用程序中可能出现的原因NoClassDefFoundError可能有很多,例如:

  • APK 中有超过 65536 个方法。解决方案是启用MultiDEX,您可以关注这个官方的 Android 资源https://developer.android.com/studio/build/multidex#mdex-gradle
  • 在某些情况下,仅启用MultiDEX是不够的,您需要在主 DEX 文件中声明一些类。基本上,您只需要将缺少的类添加到文件中,因此正如 Dean Wild 指出的那样,它们会在应用程序启动时加载。这是因为有时构建工具在计算要添加的类时可能会遇到麻烦。官方文档:https ://developer.android.com/studio/build/multidex#keep
  • 如果您已经覆盖了Application类以使用一些自定义代码对其进行扩展,那么您可能必须从MultiDexApplication类而不是类继承Application
  • 在测试时,如果您使用 anyMonitoringInstrumentationAndroidJUnitRunner工具,您将不会NoClassDefFoundError遇到 ,但您可能会以其他方式得到它们。如果是这种情况,那么只需在方法中添加以下代码onCreate()

onCreate()方法内容:

public void onCreate(Bundle arguments) {
    MultiDex.install(getTargetContext());
    super.onCreate(arguments);
}
于 2018-06-19T09:57:51.697 回答
0

针对 SDK ICS 或更高版本构建您的项目。

他们已经在 ICS+ 中自动加载了 AsyncTask。这就是问题所在。

于 2013-10-22T00:29:08.450 回答
0

启用 multidex 导致我出现了这个问题。我需要 multidex,因为我包含了整个 google play services 库。通过只包含我需要的组件(在我的例子中是 GCM),我能够禁用 multidex 并防止这个问题。

我知道这不是一个真正的修复,但我认为从我所读到的内容中,如果可能的话,应该避免使用 multidex。

于 2015-06-05T10:42:34.110 回答