Hey! My name is Stéphane Nicolas. Senior Android Dev @ Groupon ~20 years of Java coding OSS: RoboSpice, RoboGuice, BoundBox, Injects, Dart, … snicolas stephanenicolas +stephane nicolas
BYTECODE WEAVING On Android : static byte code weaving performed right after compilation. We got a full stack : the INJECTS projects github.com/stephanenicolas/injects
๏ Complex libs ๏ Non standard builds —> High Maintenance ๏ Only jar & class files, not dex ๏ Jack n’Jill ? —> No one knows about Jayce ๏ Modifications are invisible BYTECODE WEAVING ✓ Simple to use ✓ No boiler plate code ✓ As easy as a gradle plugin ✓ Extremely powerful ✓ ‘de facto standard’ API : Javassist.
AST MANIPULATION Abstract Syntax Trees (AST) : data structures to represent Java statements, they are used internally by Java compilers. Lombok for Java : projectlombok.org Hrisey for Android : github.com/mg6maciej/hrisey
๏ Harder than byte code. ๏ Non standard (Android could focus on Javac) ๏ Jack n’Jill ? —> No one knows about Jayce ๏ Modifications are invisible ✓ Simple to use ✓ No boiler plate code ✓ As easy as a gradle plugin ✓ Extremely powerful AST MANIPULATION
ANNOTATION PROCESSING Annotation processing allows to generate new code. Some boiler plate is needed to invoke it. Here, ButterKnife generates code to bind resources and views to fields of an Activity.
๏ API is difficult ๏ Impossible to modify code. Only new code can be generated ๏ Every lib based on reflection has to be rewritten ๏ Needs boiler plate to invoke generated code ✓ Simple to use ✓ Java Standard ✓ Relatively powerful ANNOTATION PROCESSING
In DI & Binding libs generated code is used to manipulate non private members : • access fields • call methods • call constructors GENERATED CODE —> Like reflection !
1) Make it easy to adapt reflection based Java libs to Android. 2) Get the best of reflection (ease) and annotation processing (speed) 3) Hide generated code RNЯ objectives
RNЯ: 3 steps 1. Define RNЯ classes: 100 % compatible with reflection & fill these data structures during annotation processing time . 2. Generate code so that RNЯ becomes available at runtime. 3. Generate code that allows modification of members (access fields, invoke methods and constructors).
Step 1 : Results After this step, Annotation Processor can use the reflection API. We manipulate fields, methods, constructors & classes… before they are compiled ! Unification of Annotation Processing and Reflection API By itself it is an important theoretical achievement in Java.
RNЯ classes • They are 100 % compatible with the reflection API classes • RNЯ classes are filled during annotation processing • RNЯ classes are generated to become accessible at runtime via Class.forName(‘’test.Foo‘’)
Step 2 : Results RNЯ reflection classes : • accessible to libs/apps at runtime • provide read-only access to reflection information • are faster than reflection on Android. But they are read-only, unlike native reflection.
Step 3 : Results Step 3 extends step 2. Now, RNЯ reflection classes : • accessible to libs/apps at runtime • provide read/write access to reflection information • are faster than reflection on Android. (Oh, Btw, there is a little detail that we gently omitted : annotation implementations…And we are proud to have succeeded in doing it.)
RNЯ Guice : Why it failed • Guice uses a lot of reflection, many if not all features of reflection —>The fork introduced a high volume of changes… and potential bugs. • Reflection is also linked to the compiler at a very low level via class symbolication / class literals : Reflection Compiler Symbole
RNЯ Guice fork : take 2 Minimize the amount of changes in Guice to use RNЯ. Bypass native reflection for members access via reflectors. And only that. Guice RNЯ Guice scan classes members Processing access field invoke methods create instances
Conclusions RNЯ - Step 1, unifies Annotation Processing and Reflection at compile-time. RNЯ - Step 2 and Step 3 are a generalization of all the work that has been done on Android related to Annotation Processing to circumvent Reflection. RNЯ demonstrates that this approach is feasible.
Conclusions RNЯ, got initiated by our desire to achieve a faster DI for Android. We plan to release soon a new version of Guice / RoboGuice based on the RNЯ reflectors. Not based on the full RNЯ solution.