A simple example Byte Code Weaving for Android Goal : Log all life cycle methods of an Activity With LogLifeCycle, you just have to : Use the LogLifeCycle Gradle plugin inside your build.gradle file Then simply annotate every activity you wanna log : https://github.com/stephanenicolas/loglifecycle apply plugin: 'loglifecycle' @LogLifeCycle public class MainActivity extends Activity { ... } Activity build.gradle lundi 22 septembre 14
Presentation plan Byte Code Weaving for Android I. Byte Code Weaving for Android 1) Dynamic Vs. Static Byte Code Weaving 2) Why Dynamic Byte Code weaving can’t work on Android 3) Transforming classes during Android Post-Compilation build phase 4) Javassist API : much simpler than annotation processing 5) Gradle & Maven examples II. AfterBurner & Mimic : 2 libs to ease Byte Code Weaving on Android 1) Mimic : Templating byte code injection 2) Mimic : a simple use case 3) AfterBurner : Fluent API for byte code injection 4) AfterBurner : a simple use case lundi 22 septembre 14
Byte Code Weaving for Android ‘‘ Byte Code Weaving is a technique for changing the byte code of compiled Java classes. ’’ From oracle docs : docs.oracle.com/cd/E17904_01/doc.1111/e16596/bestpractice.htm Section 4.1 Changing Compiled Java Classes with Byte Code Weaving lundi 22 septembre 14
2 ways to weave Byte Code Byte Code Weaving for Android Dynamic Byte Code Weaving at Runtime Java classes are intercepted prior to being loaded by the class loader. Byte Code is modified at runtime. Static Byte Code Weaving at Post Compile Time Java classes Byte Code is m o d i f i e d r i g h t a f t e r compilation by javac. B y t e C o d e i s m o d i f i e d during build process. lundi 22 septembre 14
Dynamic Weaving Byte Code Weaving for Android Java classes are intercepted prior to being loaded by the class loader. The interceptor is called a Java agent. Java agents are defined by a standard API : •java.lang.instrument.ClassTransformer •java.lang.instrument.Instrumentation •simple to define agents •no changes to build degrades performance lundi 22 septembre 14
There are no java agents on Android Dalvik / ART ! Byte Code Weaving for Android The closest thing to a java agent is an Instrumentation. From stackoverflow.com/q/12725279/693752 lundi 22 septembre 14
What is Java Instrumentation ? Byte Code Weaving for Android android.app.Instrumentation API : •void callActivityOnCreate (Activity activity, Bundle icicle) •void callActivityOnDestroy (Activity activity) •void callActivityOnPause (Activity activity) •void callActivityOnResume (Activity activity) •void callActivityOnStart (Activity activity) •void callActivityOnStop (Activity activity) •void callApplicationOnCreate (Application app) Android instrumentation is used to pilot application and activities, usually during testing (to provide mocked resources). lundi 22 septembre 14
Limitations of Instrumentation Byte Code Weaving for Android The closest thing to a java agent is an Instrumentation. From stackoverflow.com/q/12725279/693752 Instrumentation : •is Activity centric •can slow down apps easily •can alter behavior before or after a hook. i.e it can’t fill all your views inflated after setContentView() inside onCreate() setContentView() onCreate() It is far less powerful than a Java agent. lundi 22 septembre 14
Byte Code Weaving for Android There are 2 options to weave Android Byte Code. 1)after compilation by javac and before dexing 2)after dexing Solution 2 requires that we find tools that can read/write Byte Code in the dex format. Solution 1 offers greater compatibility with existing Java Byte Code manipulation tools. Post Compilation on Android lundi 22 septembre 14
Static Weaving Byte Code Weaving for Android For Gradle : • Javassist gradle plugin github.com/darylteo/gradle-plugins For Maven : • Javassist maven plugin github.com/icon-Systemhaus-GmbH/javassist-maven-plugin A de facto standard library can be used : Javassist Highly depends on build tools. lundi 22 septembre 14
Gradle & Maven Javassist plugins Byte Code Weaving for Android Both Javassist gradle & maven plugins share a simple interface to create class transformers : •void applyTransformations(CtClass classToTransform) •boolean shouldTransform(final CtClass candidateClass) developers can use them with the build tool of their choice. https://github.com/stephanenicolas/javassist-build-plugin-api lundi 22 septembre 14
Javassist Byte Code Weaving for Android Javassist offers : a very simple API, quite close to Java standard reflection API it is FAR FAR simpler than annotation processing API de facto standard for Byte Code manipulation on JVM (used by Jboss, EasyMock, Mockito, JPA implementations, etc.) it works with everything that interprets Java Byte Code it cannot manipulate DEX files (see fork: github.com/crimsonwoods/javassist-android) lundi 22 septembre 14
Byte Code Weaving for Android A ClassTransformer example https://github.com/stephanenicolas/afterburner cd to afterburner-sample-processor see ExampleProcessor (based on AfterBurner - optional) lundi 22 septembre 14
Fine grain Mimic’ing enum MimicMode { /** Beginning of target method. */ AT_BEGINNING, /** End of target method.*/ BEFORE_RETURN, /** Before a call to an overridden method.*/ BEFORE_SUPER, /** After a call to an overridden method.*/ AFTER_SUPER, /** Instead of a call to an overridden method.*/ REPLACE_SUPER, /** Before a call to a given method.*/ BEFORE, /** After a call to a given method.*/ AFTER; } Byte Code Weaving for Android lundi 22 septembre 14
Mimic : use case Activity Android Framework RoboActivity Library App MyRoboActivity RoboActivity is a complex class that provides nice features : 200 LOCs +. Byte Code Weaving for Android Templating Byte Code Injection lundi 22 septembre 14
Mimic : use case Library App BUT all those classes have the exact same code as RoboActivity. The only difference is their super class. Byte Code Weaving for Android RoboActivity RoboFragmentActivity RoboTabActivity RoboTabActivity RoboSherlockActivity RoboActionBarActivity RoboListActivity RoboActivity RoboFragmentActivity RoboTabActivity RoboTabActivity RoboSherlockActivity RoboActionBarActivity RoboListActivity Templating Byte Code Injection lundi 22 septembre 14
Mimic : use case Byte Code Weaving for Android Templating Byte Code Injection class RoboActivity extends Activity { void onCreate(Bundle b) {...} void onXXX() {...} } @RoboActivity class Example extends WhatEverActivity { @Override void onCreate(Bundle b) { super.onCreate(b); } } Mimic provides an extensible mechanism to create powerful custom annotations for your libs. lundi 22 septembre 14
Open futures Some ideas that could also become ASRs : • ButterKnife/RoboGuice -> @InjectView • Dagger/RoboGuice -> @Inject • Otto/RoboGuice/EventBus -> @Observes • Memento/IcePick -> @Statefull • Hugo -> @Log • Wire/Jackson2/gson to generate (de)serialization code for Pojos • to be continued... Remove boiler plate from our apps ! --> Just code what is worth coding <-- Byte Code Weaving for Android lundi 22 septembre 14