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
Slide 4
Slide 4 text
THE TALK
• Motivations
• Reflection
• Alternatives to reflection
• RNЯ : reflection no reflection
• Conclusion
• Strongly recommend knowledge of:
• DI & bindings (ButterKnife, Dart, etc.)
• Annotation processing
Slide 5
Slide 5 text
ROBOGUICE
• —> But slow
• Feature Rich
• Easy to configure, and use
• No manual graph definition
BYTECODE WEAVING
On Android : static byte code weaving
performed right after compilation.
We got a full stack : the INJECTS projects
github.com/stephanenicolas/injects
Slide 14
Slide 14 text
๏ 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.
Slide 15
Slide 15 text
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
Slide 16
Slide 16 text
๏ 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
Slide 17
Slide 17 text
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.
Slide 18
Slide 18 text
๏ 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 !
Slide 21
Slide 21 text
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
Slide 22
Slide 22 text
RNЯ
Generate reflection like code
via annotation processing
Slide 23
Slide 23 text
No content
Slide 24
Slide 24 text
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).
Slide 25
Slide 25 text
Step 1 : Annotation processing time
RNЯ classes
Annotation Processing Compiler
Annotation
Processor using
reflection
Generated
Java Source
Slide 26
Slide 26 text
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.
Slide 27
Slide 27 text
Step 2 : RNЯ accessible at runtime
Generate code to fill RNЯ classes
Annotation Processing Compiler App
RNЯ
Reflection
Slide 28
Slide 28 text
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‘’)
Slide 29
Slide 29 text
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.
Slide 30
Slide 30 text
Step 3 : Write access
Generate code
to fill RNЯ classes
Annotation Processing Compiler App
RNЯ
Reflection
Class
Reflectors
Slide 31
Slide 31 text
RNЯ reflectors
Field
access
Methods
invocation
Constructors
invocation
Slide 32
Slide 32 text
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.)
Slide 33
Slide 33 text
RNЯ works, what next ?
The general context of research on RNЯ was improving DI speed.
so let’s fork Guice !
It should be as simple as replacing native Reflection with RNЯ reflection.
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
Slide 36
Slide 36 text
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
Slide 37
Slide 37 text
RNЯ Guice fork : results
Slide 38
Slide 38 text
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.
Slide 39
Slide 39 text
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.
Slide 40
Slide 40 text
Java
Source
Byte
Code
App
JVM
Compiler
The solution might be elsewhere…
AOT compilation +
JIT reflection code
Slide 41
Slide 41 text
Thanks for attending
this reflection on reflection
Questions ?
Comments ?