简体   繁体   中英

NoClassDefFoundError only some devices, only from playstore? is this even possible?

This problem is like a logic puzzle. you have been warned.

I'm working on a library that is integrated to other apps. One person complained that they are seeing crashes from only SOME of their users:

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)

and the line of code where the crash is happening is at:

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

and in the same package, there is...

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

Here is what I've been told or i know:

  1. this crash only happens on some users. (but based on Google Play crash reporting. so is that just not accurate? or is the sample generated too slowly?)

  2. the developer cant reproduce this error in house, even with a signed build. (i've checked the signed build and dedexed it to see that the class exists in the src, so i believe him)

  3. but when the app was live on the play store, and people downloaded his new version, he suddenly saw crash reports from some people, believed to be mostly devices 2.3.x though this is unconfirmed)

  4. he claims he updated to "api 17". when people say that, do they mean build target 17? or do people mean updating to ADT 17? because i've known ADT mucking up the lib/libs folder issue.

  5. he seems to be using eclipse.

  6. he is calling my code from cocos2d-x for Android, by doing a handler.post()

How is this even possible?

I'm confused on why only SOME of the users are seeing NoClassDefFoundError ?? Is that a huge google play crash reporting issue? like, were all users seeing it, but then google play says only some of the users were seeing this issue? (i haven't verified with the developer, but im fairly certain he tested by downloading a live version from the Play store and he didn't see any errors, and that piece of code is run fairly ).

From what i understand, NoClassDefFoundError is only when the class exists via one of the three classloaders, but then at runtime, none of the classloaders can find the particular class.

is this a proguard issue? i've read that proguard is only run at release time.

is this an AsyncTask issue? i've read that AsyncTasks have to be instantiated the very first time on a UI Thread. although, i'm not sure why that would cause a NoClassDefFoundError .

any thoughts?

There could be a number of reasons why NoClassDefFoundError could occur in your app like:

  • Having more than 65536 methods in your APK. The solution is to enable MultiDEX , which you can following this official Android resource https://developer.android.com/studio/build/multidex#mdex-gradle
  • In some cases, enabling MultiDEX is not enough, and you need to declare some of your classes in the primary DEX file. Basically you just need to add the missing classes into a file, so they are loaded on app startup as Dean Wild pointed out. This is because sometimes the build tools might have troubles doing the calculations of which classes to add. Official documentation: https://developer.android.com/studio/build/multidex#keep
  • If you have overridden the Application class to extend it with some custom code, then you might have to inherit from MultiDexApplication class and not from the Application class.
  • While testing, if you use the either MonitoringInstrumentation or an AndroidJUnitRunner instrumentation, you won't incur into NoClassDefFoundError , but you might get them otherwise. If that's the case, then just add the following code in the onCreate() method:

onCreate() method content:

public void onCreate(Bundle arguments) {
    MultiDex.install(getTargetContext());
    super.onCreate(arguments);
}

Build your project against SDK ICS or above.

they've automatically loaded AsyncTask in ICS+. this was the issue.

Enabling multidex caused this issue to arise for me. I needed multidex because I was including the entire google play services library. By only including the components I needed (GCM in my case), I was able to disable multidex and prevent this issue.

Not a real fix I know, but I think multidex should be avoided if possible from what I have read.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM