Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NoClassDefFoundError/ExceptionInInitializerError on Android 2.3.3 and Jackson 2.9.0 #1802

Closed
johnjohndoe opened this issue Oct 20, 2017 · 8 comments

Comments

@johnjohndoe
Copy link
Contributor

johnjohndoe commented Oct 20, 2017

I discovered a NoClassDefFoundError/ExceptionInInitializerError when I run this Android app in the following environment:

  • Samsung GT-I9000
  • Android 2.3.3 (API level 8, Froyo)
  • no Google Play Services installed
  • com.fasterxml.jackson.core:jackson-databind:2.9.0 - 2.9.2
  • crash happens for DEBUG and RELEASE builds

Here is the excerpt which causes the crash. The full source code can be found here (commit: 4da721846ad4c9bca030fc1167aff3d8754abb72).

111 SimpleModule module = new SimpleModule();
112 module.addDeserializer(Circuit.class, new CircuitDeserializer());
113 ObjectMapper objectMapper = new ObjectMapper(); // <-- crash
114 objectMapper.registerModule(module);

The following stacktrace is generated when I open the FaqActivity from the toolbar menu:

java.lang.ExceptionInInitializerError
    at com.fasterxml.jackson.databind.ObjectMapper.<init>(ObjectMapper.java:577)
    at com.fasterxml.jackson.databind.ObjectMapper.<init>(ObjectMapper.java:480)
    at de.avpptr.umweltzone.utils.ContentProvider.getContent(ContentProvider.java:113)
    at de.avpptr.umweltzone.utils.ContentProvider.getContent(ContentProvider.java:98)
    at de.avpptr.umweltzone.utils.ContentProvider.getFaqs(ContentProvider.java:68)
    at de.avpptr.umweltzone.faqs.FaqActivity.onCreate(FaqActivity.java:40)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615)
    ...
Caused by: java.lang.ExceptionInInitializerError
    at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.<clinit>(BasicDeserializerFactory.java:49)
    ... 19 more
Caused by: java.lang.NoClassDefFoundError: com.fasterxml.jackson.databind.util.ClassUtil
    at com.fasterxml.jackson.databind.PropertyName.<init>(PropertyName.java:66)
    at com.fasterxml.jackson.databind.PropertyName.<clinit>(PropertyName.java:29)
    ... 20 more

Findings

  • The crash can be reproduced with the system-images;android-10;google_apis;x86 emulator image (Android 2.3.3, Google APIs)
  • The crash does not occur when I use jackson-databind:2.8.10.
  • The crash does not happen on another device: Nexus 5, Android 6.0.1, Google Play Services installed.
  • The crash does not occur on Android 4.1, API level 16 (tested with system-images;android-16;google_apis;x86 emulator).

Related issues

@cowtowncoder
Copy link
Member

cowtowncoder commented Oct 20, 2017

And just to make sure: class ClassUtil does exist in jar used (and package built, used)?
I guess such exception is often result of a failure in static initializer so perhaps that doesn't tell much yet.

However... I don't see any significant initialization for this class; about the only thing is:

    private final static Iterator<?> EMPTY_ITERATOR = Collections.emptyIterator();

This method was added in JDK 1.7, so could that be missing from specific Android SDK version?

If so, I guess it would be possible to retrofit this to avoid the problem (and leave 3.0 as is); however, 2.9 is meant to rely on JDK 7 so this is probably not the only place for similar issues.

@johnjohndoe
Copy link
Contributor Author

And just to make sure: class ClassUtil does exist in jar used (and package built, used)?

Do you mean in jackson-databind-2.9.0.jar? Yes, if I unpack the .jar I find ClassUtil.class in com/fasterxml/jackson/databind/util. Same for v.2.9.1 and v.2.9.2.

johnjohndoe added a commit to Umweltzone/Umweltzone that referenced this issue Oct 22, 2017
+ Happens on Android 2.3.3 (API level 8, Froyo) with Jackson 2.9.0.
+ See: FasterXML/jackson-databind#1802
@cowtowncoder
Copy link
Member

cowtowncoder commented Oct 23, 2017

@joelittlejohn Looking at:

https://developer.android.com/about/dashboards/index.html

I think that the root cause is that this old Android version does not include method emptyIterator from java.util.Collections, which was added in JDK 1.7.
This is actually sort of dup of #1134 (assuming root cause is indeed the same), but since 2.9 requires JDK 7 baseline, it is not a bug but limitation wrt Android SDK with which Jackson 2.9 may be used.

Looking at:

https://developer.android.com/reference/java/util/Collections.html#emptyIterator()

limit appears to be "API level 19" which means Android 4.4, I think, as per:

https://developer.android.com/about/dashboards/index.html

I will add a note on Jackson 2.9 release page:

https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.9

What is interesting, however, is that I thought Jackson 2.8 would have similar limitation since it uses Java 7 features.

As I said, if anyone wants to create patch to change this usage (and other similar small problems), I am not against 2.9 patch, although I will not merge those for Jackson 3.0.

@joelittlejohn
Copy link
Contributor

@johnjohndoe ☝️

@johnjohndoe
Copy link
Contributor Author

Thank you for the explanation. Are you going to backport this? If v.2.9.x will no longer support these JDK / Android versions this notice should get a prominent place in the docs.

@cowtowncoder
Copy link
Member

Well this has been mentioned, announced and included as a warning for 2.8 release:

https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.8

so it's not news per se. Unfortunately however feedback loop between Jackson project and Android developers (I don't think anyone on core team develops on Android unfortunately) has been... well, high-latency one. You have been very helpful and I appreciate that.

But yes, it should be prominently included in 3.0 notes. Ideally based on solid information and tests done by someone who develops on Android.

As to backporting: if someone wants to work on this and verify necessary changes, I will work with that person and merge PR(s) as necessary. I just do not have either time or experience to do it on my own, to properly verify fixes (much less automate it).

@johnjohndoe
Copy link
Contributor Author

johnjohndoe commented Oct 26, 2017

Thank you again for pointing me to the release notes.

Thinking about it, I am not sure if backporting is very much worth the effort since Android apps tend to raise their minimum SDK level more and more. Google themselves dictates this because they raise version ("minimum Android API level of 14") in widely used libraries such as Google Play Services library. The other question which has to be answered by each app individually is how many users are actually still using devices with older Android versions.

One thing I would be interested in is if you are planning to release 2.8.x versions if security issues or major bugs are discovered which apply to this minor version?

@cowtowncoder
Copy link
Member

@johnjohndoe Yes, there's diminishing return on back-porting, and Google does tend to push for newer versions (since older versions are costly to support for them too).

And yes, security issues are a class of problems for which new versions are theoretically possible for even otherwise closed branches. 2.8 is not yet officially closed, however, and I suspect I will be doing full 2.8.11 release at some point. Beyond this, micro-patches are a possibility.
As to major bugs, perhaps, depends on type of bug in question. I don't think I have done that yet for a closed minor branch (unlike security patch or two), but I would not rule that out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants