Skip to content
This repository has been archived by the owner on Nov 5, 2019. It is now read-only.

Afterburner module not working with Android #2

Closed
marcosalis opened this issue Jul 24, 2012 · 13 comments
Closed

Afterburner module not working with Android #2

marcosalis opened this issue Jul 24, 2012 · 13 comments

Comments

@marcosalis
Copy link

I'm successfully using Jackson 1.9.8 for JSON data-binding in an Android application.
I've tried using the experimental Afterburner module (v. 1.9.4) with the ASM 4.0 jar, but I get this exception when I try to serialize an object:

07-24 10:22:25.444: E/dalvikvm(354): ERROR: defineClass(0x44e8d7a8, com.example.Foo$Access4JacksonSerializer, 0x44e8cbe8, 0, 1265, 0x0)
07-24 10:22:25.444: E/dalvikvm(354): ERROR: defineClass(0x44fe2438, com.example.Foo$Access4JacksonSerializer, 0x44e8cbe8, 0, 1265, 0x0)
07-24 10:22:25.554: I/TestRunner(354): java.lang.UnsupportedOperationException: can't load this type of class file
07-24 10:22:25.554: I/TestRunner(354): at java.lang.VMClassLoader.defineClass(Native Method)
07-24 10:22:25.554: I/TestRunner(354): at java.lang.ClassLoader.defineClass(ClassLoader.java:338)
07-24 10:22:25.554: I/TestRunner(354): at java.lang.ClassLoader.defineClass(ClassLoader.java:301)
07-24 10:22:25.554: I/TestRunner(354): at com.fasterxml.jackson.module.afterburner.util.MyClassLoader.loadAndResolve(MyClassLoader.java:52)
07-24 10:22:25.554: I/TestRunner(354): at com.fasterxml.jackson.module.afterburner.ser.PropertyAccessorCollector.generateAccessorClass(PropertyAccessorCollector.java:161)
07-24 10:22:25.554: I/TestRunner(354): at com.fasterxml.jackson.module.afterburner.ser.PropertyAccessorCollector.findAccessor(PropertyAccessorCollector.java:101)
07-24 10:22:25.554: I/TestRunner(354): at com.fasterxml.jackson.module.afterburner.ser.SerializerModifier.changeProperties(SerializerModifier.java:48)
07-24 10:22:25.554: I/TestRunner(354): at org.codehaus.jackson.map.ser.BeanSerializerFactory.constructBeanSerializer(BeanSerializerFactory.java:442)
07-24 10:22:25.554: I/TestRunner(354): at org.codehaus.jackson.map.ser.BeanSerializerFactory.findBeanSerializer(BeanSerializerFactory.java:347)
07-24 10:22:25.554: I/TestRunner(354): at org.codehaus.jackson.map.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:291)
07-24 10:22:25.554: I/TestRunner(354): at org.codehaus.jackson.map.ser.StdSerializerProvider._createUntypedSerializer(StdSerializerProvider.java:782)
07-24 10:22:25.554: I/TestRunner(354): at org.codehaus.jackson.map.ser.StdSerializerProvider._createAndCacheUntypedSerializer(StdSerializerProvider.java:735)
07-24 10:22:25.554: I/TestRunner(354): at org.codehaus.jackson.map.ser.StdSerializerProvider.findValueSerializer(StdSerializerProvider.java:344)
07-24 10:22:25.554: I/TestRunner(354): at org.codehaus.jackson.map.ser.StdSerializerProvider.findTypedValueSerializer(StdSerializerProvider.java:420)
07-24 10:22:25.554: I/TestRunner(354): at org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:601)
07-24 10:22:25.554: I/TestRunner(354): at org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:256)
07-24 10:22:25.554: I/TestRunner(354): at org.codehaus.jackson.map.ObjectMapper._configAndWriteValue(ObjectMapper.java:2575)
07-24 10:22:25.554: I/TestRunner(354): at org.codehaus.jackson.map.ObjectMapper.writeValueAsString(ObjectMapper.java:2097)

Is ASM or the module incompatible with the Dalvik bytecode?
Thank you in advance!

@cowtowncoder
Copy link
Member

I will have to Google to know that for sure; I don't recall discussions on this on ASM mailing lists.

@cowtowncoder
Copy link
Member

Hmhm. I think that Android actually requires standard Java bytecode to be converted to Dex on installation or such, which would preclude dynamic loading of standard bytecode. And this would mean that Afterburner can not be used as is on Android.

I suspect there must be Android-specific libraries that allow doing something similar to Asm however. If so, it might be possible to have "AndroidBurner" variation, to achieve the same end result, I think. As long as generated classes can be loaded dynamically by DVM.

@marcosalis
Copy link
Author

There are libraries that allow dynamic bytecode conversion to Dalvik format (dex), but I've never used them and I honestly don't know how they work and if they are suitable for this kind of dynamic bytecode loading.
Have a look at this posts: http://stackoverflow.com/questions/2610995/dynamically-generating-dalvik-bytecode-into-a-running-dalvik-android-application and the project http://code.google.com/p/dexmaker/

Whenever I'll find the time to investigate more on this topic I'm gonna certainly let you know. That would be great to have an "out-of-the-box" working solution for the Android platform too, anyway, I feel like many developers would take advantage of such optimization on a so performance-critical architecture as mobile devices.
Thanks anyway for your consideration!

@cowtowncoder
Copy link
Member

Thank you for the idea. I agree in that this would be useful -- hopefully we get something like this implemented eventually.
And this issue entry should be a good starting point with some information whenever there is enough itch for an individual to scratch. :-)

@jbarwick
Copy link

itch itch...scratch

I was just thinking how useful it would be to be able to speed up Jackson De/Serialization.

The reported benchmarks of 30-40% improvement is HUGE. Now, I could write the app to do JSON document parsing "brute force", but Jackson does give us a bit of formal control.

I wonder if we could do a facebook survey. Anyway, who would write this? We all would certainly appreciate the time someone put in to do it!

But alas, the comments are over 2 years old. Oh, well.

@cowtowncoder
Copy link
Member

Right, I am not aware of anyone actively working on this. I suspect there are multiple possible approaches, including both static method (of generating equivalent custom handlers) and dynamic.
I think there are tools like ASMDex that would allow dynamic approach.

Survey wouldn't hurt but I don't see it as helping a lot -- someone still needs to implement this.

@jbarwick
Copy link

Yeah. Anyway, threw away the code and am now using org.json.JSONObject.

300% performance boosts. (1 iteration) (unit tests aggregate from 27-30 seconds to 10-12 seconds)

So, now...no need. (for this project)

@cowtowncoder
Copy link
Member

Awesome! This improvement is in line with what I have seen on server-side Java as well.

@eveliotc
Copy link

+1 for supporting Android, we are getting rid of org.json (+ a custom annotation/reflection based inflater) in favor of Jackson, it is certainly faster but found that large responses are taking a long time (which were the ones who make us start using Jackson at last) and I'm too lazy to implement manual parsing :)

Full exception that I get is:

    java.lang.UnsupportedOperationException: can't load this type of class file
            at java.lang.ClassLoader.defineClass(ClassLoader.java:253)
            at com.fasterxml.jackson.module.afterburner.util.MyClassLoader.loadAndResolve(MyClassLoader.java:73)
            at com.fasterxml.jackson.module.afterburner.deser.PropertyMutatorCollector.generateMutatorClass(PropertyMutatorCollector.java:170)
            at com.fasterxml.jackson.module.afterburner.deser.PropertyMutatorCollector.buildMutator(PropertyMutatorCollector.java:113)
            at com.fasterxml.jackson.module.afterburner.deser.DeserializerModifier.updateBuilder(DeserializerModifier.java:62)
            at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:281)
            at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:168)
            at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:401)
            at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:350)
            at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:263)
            at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:243)
            at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:144)
            at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:381)
            at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:3095)
            at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2989)
            at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2144)

I'm not familiar with Afterburner internals (everything's magic), but anything (like just compile time code generation) that helps speed things up for "free" is much appreciated.

@cowtowncoder
Copy link
Member

@eveliotc The problem is that as far as I understand, Android does not allow dynamically loading standard Java bytecode; but rather its own (Dalvik-specific) internal representation. Because of this, a different tool, and possibly different module (or, making this a multi-project maven, which is fine), is needed. And someone with experience/knowledge with libs needed (ASMDex has been mentioned) is a pre-requisite here. Unless I manage to find a way to work bit more on Android at work (which just might happen in near future, as it happens). :)

@eveliotc
Copy link

@cowtowncoder that'd be huge! now you let me wondering here, so far what I have understood of afterburner (pretty much from your comment, lazy you see?) is that it will generate cute bytecode to minimize overhead caused by reflection, autoboxing, etc. getting closer to optimal, so wouldn't be something similar to write a JsonDeserializer per class (or similar) at compile time? or is there something else that I am missing?

I've seen many projects for Android that hook at compile time and generate source which will remove reflection overhead and such for Android (e.g. Dagger, Groundy, etc.), then dx will get that bytecode Dalvik ready, so technically it would be actually easy to do the same for Jackson to generate a JsonDeserializer or similar per annotated class being quite close to what you'd manually write, wouldn't be?

@cowtowncoder
Copy link
Member

Quick note: DexMaker -- https://code.google.com/p/dexmaker/ -- seems like it could help in code generation for Android.

@cowtowncoder
Copy link
Member

@eveliotc I think the idea of pre-generating implementations is something that would belong to another extension project, since it works in different part of deployment cycle: Afterburner works on-the-fly, during runtime, whereas I think you are talking about something that would be part of build process. Both have their benefits and drawbacks.

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

No branches or pull requests

4 participants