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:
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?)
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)
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)
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.
he seems to be using eclipse.
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:
MultiDEX
, which you can following this official Android resource https://developer.android.com/studio/build/multidex#mdex-gradle 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 Application
class to extend it with some custom code, then you might have to inherit from MultiDexApplication
class and not from the Application
class. 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.