I know that this is not the first post of its kind, and while not all issues that may look similar are caused by the same bug in the code, there should be some at least.
Symptoms in this specific case:
Rejecting re-init on previously-failed class java.lang.Class<com.evernote.android.job.gcm.PlatformGcmService>: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/gcm/GcmTaskService;
at boolean com.evernote.android.job.GcmAvailableHelper.isGcmApiSupported(android.content.Context) (GcmAvailableHelper.java:-1)
at boolean com.evernote.android.job.JobApi.isSupported(android.content.Context) (JobApi.java:115)
at void com.evernote.android.job.JobProxy$Common.cleanUpOrphanedJob(android.content.Context, int) (JobProxy.java:286)
at void com.evernote.android.job.JobManager.schedule(com.evernote.android.job.JobRequest) (JobManager.java:176)
at int com.evernote.android.job.JobRequest.schedule() (JobRequest.java:426)
at void com.evernote.android.job.JobRequest$2.run() (JobRequest.java:455)
at void java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) (ThreadPoolExecutor.java:1162)
at void java.util.concurrent.ThreadPoolExecutor$Worker.run() (ThreadPoolExecutor.java:636)
at void java.lang.Thread.run() (Thread.java:764)
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.gcm.GcmTaskService" on path: DexPathList[[zip file ...
at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:125)
at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:379)
at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312)
at boolean com.evernote.android.job.GcmAvailableHelper.isGcmApiSupported(android.content.Context) (GcmAvailableHelper.java:-1)
at boolean com.evernote.android.job.JobApi.isSupported(android.content.Context) (JobApi.java:115)
at void com.evernote.android.job.JobProxy$Common.cleanUpOrphanedJob(android.content.Context, int) (JobProxy.java:286)
at void com.evernote.android.job.JobManager.schedule(com.evernote.android.job.JobRequest) (JobManager.java:176)
at int com.evernote.android.job.JobRequest.schedule() (JobRequest.java:426)
at void com.evernote.android.job.JobRequest$2.run() (JobRequest.java:455)
at void java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) (ThreadPoolExecutor.java:1162)
at void java.util.concurrent.ThreadPoolExecutor$Worker.run() (ThreadPoolExecutor.java:636)
at void java.lang.Thread.run() (Thread.java:764)
Rejecting re-init on previously-failed class java.lang.Class<com.evernote.android.job.gcm.PlatformGcmService>: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/gcm/GcmTaskService;
at boolean com.evernote.android.job.GcmAvailableHelper.isGcmApiSupported(android.content.Context) (GcmAvailableHelper.java:-1)
at boolean com.evernote.android.job.JobApi.isSupported(android.content.Context) (JobApi.java:115)
at void com.evernote.android.job.JobProxy$Common.cleanUpOrphanedJob(android.content.Context, int) (JobProxy.java:286)
at void com.evernote.android.job.JobManager.schedule(com.evernote.android.job.JobRequest) (JobManager.java:176)
at int com.evernote.android.job.JobRequest.schedule() (JobRequest.java:426)
at void com.evernote.android.job.JobRequest$2.run() (JobRequest.java:455)
at void java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) (ThreadPoolExecutor.java:1162)
at void java.util.concurrent.ThreadPoolExecutor$Worker.run() (ThreadPoolExecutor.java:636)
at void java.lang.Thread.run() (Thread.java:764)
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.gcm.GcmTaskService" on path: DexPathList[[zip file ...
at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:125)
at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:379)
at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312)
at boolean com.evernote.android.job.GcmAvailableHelper.isGcmApiSupported(android.content.Context) (GcmAvailableHelper.java:-1)
at boolean com.evernote.android.job.JobApi.isSupported(android.content.Context) (JobApi.java:115)
at void com.evernote.android.job.JobProxy$Common.cleanUpOrphanedJob(android.content.Context, int) (JobProxy.java:286)
at void com.evernote.android.job.JobManager.schedule(com.evernote.android.job.JobRequest) (JobManager.java:176)
at int com.evernote.android.job.JobRequest.schedule() (JobRequest.java:426)
at void com.evernote.android.job.JobRequest$2.run() (JobRequest.java:455)
at void java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) (ThreadPoolExecutor.java:1162)
at void java.util.concurrent.ThreadPoolExecutor$Worker.run() (ThreadPoolExecutor.java:636)
at void java.lang.Thread.run() (Thread.java:764)
Prerequisites: I don't have GCM included and I don't want it.
Since most or the related issues were closed without solution, I started looking in to this myself and I think I've found the reason that leads to the above exceptions:
Obviously this cannot work. Once the GcmAvailableHelper class gets loaded, the used types are tried to be loaded, but PlatformGcmService cannot be loaded because its parent class GcmTaskService isn't included.
This can be easily fixed in various ways, probably no need to elaborate any further.
What I would really be concerned about: Could this be fixed for version 1.2.6, like as 1.2.6.1 or 1.2.7?
Thanks!
This should be a warning and not crashing your app. Can you confirm it's crashing your app?
This is not the warning from the catch clauses inside GcmAvailableHelper that you had recently surrounded with "if (Build.Debug)".
It doesn't even get to that point because the GcmAvailableHelper class cannot be loaded at all.
Is it crashing the app? I'm asking because some devices log error messages on their own, but they don't crash and shouldn't be.
Hm, whether the app is crashing or not shouldn't be a measure to determine if there's a bug or not ;-)
And whatever mysterious situation you are referring to, I'm pretty sure that this is not the case here, as from the call stack we can see this:
Though,, the actual problem is not about putting the call to isSupported inside the try...catch. As I tried to explain in my previous post, the problem lies in the GcmAvailableHelper class. This class should not use types for which it is actually meant to check for existance (or in this case using types derived from such types)
We're using the same code in production and don't see any issues with that. Importing classes that aren't available at runtime is no problem. The isSupported() method checks first if the class is available. If not, then it's not calling any of these classes.
public static boolean isGcmApiSupported(Context context) {
try {
return GCM_IN_CLASSPATH && ...
} catch (Throwable t) {
// ...
return false;
}
}
If I could reproduce an issue, then I would fix it. The library has to check whether the class is available. Can you reproduce the issue in the emulator?
Yes I can reproduce it in the emulator.
Just look a bit closer at the error messages:
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.gcm.GcmTaskService" on path: DexPathList[[zip file ...
Rejecting re-init on previously-failed class java.lang.Class
This means that: GcmTaskService cannot be instantiated because its base class GcmTaskService is not available (since we don't have the Google dependency included)
What happens exactly is this and in the following order:
This failure appears in two different ways in the log:
The latter ("Rejecting re-init") appears because the class loading process is not repeated when it has already failed once for a class.
But it's not crashing, is it?
It is crashing the thread and cleanUpOrphanedJob is never completed
Do you need any more information from me?
Actually I'm reporting a bug here,, this shouldn't be labeled as a question ;-)
I've tried it once again. I load the library without the GCM dependency and it's definitely not crashing. Please provide a sample application with exact steps how to reproduce the crash. I simply can't reproduce what you're describing.
Our app was previously using GCM and we dropped this. It is happening after upgrading.
Then it comes to the cleanUpOrphanedJob call which is calling jobApi.isSupported which is checking in turn for GMC.
So, to reproduce, you'll need to:
This way, you should see this error.
Please see the PR. This should fix it but I haven't tested yet.
They key would be to avoid the runtime loading the PlatformGcmService class, which it can't load because its superclass GcmTaskService (from the google package) does not exist.
Your PR #490 doesn't make a difference. I think you're running into this issue: https://github.com/evernote/android-job/wiki/FAQ#how-can-i-remove-the-gcm-dependency-from-my-app You should give this workaround a try.
Unfortunately this is not the issue that you are referring to.
I can say this with absolute confidence because we had experienced this "FAQ issue" as well!
We saw the error "Unable to instantiate service..." and it could be fixed by making the entries that you're suggesting in the FAQ.
I even checked this again just recently. I removed the service-delete-entry from the manifest and then I got the documented error again:
"Unable to instantiate service..."
But the error that I'm reporting here is different:
"ClassNotFoundException: Didn't find class "com.google.android.gms.gcm.GcmTaskService"
And it still occurs even after adding the suggested entries to the manifest (as mentioned: adding these entries _does_ has the effect that the "FAQ-Error" disappears but it doesn't eliminate the error that I'm describing in this thread.
Whether you can reproduce this or not, shouldn't matter that much in this case. It happens in cases and the callstack proves that. With the callstack it is even trivial to follow the function calls that are executed when it comes to that Exception.
I closed the PR now and created a new one with the most trivial fix one could think of:
From the callstack we can see that the exception is thrown in the Method JobProxy.cleanUpOrphanedJob when if calls jobApi.isSupported(context).
The call to isSupported was not inside a try block, and that's why the whole thing ended up in an "unhandled" Exception (=Crash).
With the latest PR I have simply moved the call to isSupported() to the inside of the try block.
That should definetely fix the situation and doesn't impose any significant risk for regressions.
I hope you'll find this change acceptable, so that we can finally settle this issue... :-)
Thanks a lot for your patience :-)
Thanks for PR. I'll include this in the next version
Thank you very much!
We're not ready for 1.3 (it's still alpha anyway), but we need to roll out a new version of our app in the next 2-3 weeks.
Is there a chance for a patched 1.2.6 or 1.2.7 version?
Unlikely. But I'm going to publish a new version over the weekend that should be stable (hopefully) and very close to the final 1.3.0.
Can the 1.3.0 version be configured to behave exactly like the 1.2.6 version?
Could we rely on that?
What I mean is: Is 1.3 the same like before just with WorkManager added as an alternative?
Or does it include global changes that also introduce differences in common behavior?
Yes, WorkManager can completely be turned off. It's also not a necessary dependency similar to GCM
OK, good! But the existing scheduling methods and the common implementation - are they unchanged?
I mean, can we upgrade to 1.3.0 without significant regression risks?
Or would we need to go through another test phase with 1.3.0?
I've published a new release 1.3.0-alpha04. Please let me know if this issue is fixed there. I appreciate all the help.
Now that you even followed both approaches that I've been suggesting, we should be on the safe side :-)
I'm still concerned about the alpha state, though:
But the existing scheduling methods and the common implementation - are they unchanged?
I mean, can we upgrade to 1.3.0 without significant regression risks?
Or would we need to go through another test phase with 1.3.0?
I don't expect any further issues. If there aren't issues, then I'd release this as stable as is.
@vRallev
is there a chance to have 1.3.0 stable soon? We also experience this bug, but I do not want to use an alpha version in our app.
Otherwise I'll patch this in latest stable release, if possible.
Most helpful comment
@vRallev
is there a chance to have 1.3.0 stable soon? We also experience this bug, but I do not want to use an alpha version in our app.
Otherwise I'll patch this in latest stable release, if possible.