Upload
guardsquare
View
2.218
Download
1
Embed Size (px)
Citation preview
The Jack and Jillbuild system
Eric Lafortune
Developer of ProGuard and DexGuard
CTO at GuardSquarewww.guardsquare.com
The Jack and Jill build system
Inside the build systemand the runtime
Practical implications and results
Jack and Jill
● Now default in build process of AOSP
● Optional in Gradle build process:
android { defaultConfig { useJack true ... } ...}
android { defaultConfig { useJack true ... } ...}
com.android.tools.build:gradle:2.0.0
android { defaultConfig { jackOptions { enabled true jackInProcess true } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 }
... } ...}
android { defaultConfig { jackOptions { enabled true jackInProcess true } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 }
... } ...}
Jack and Jillcom.android.tools.build:gradle:2.1.0 alpha1
android { defaultConfig { jackOptions { enabled true jackInProcess true } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 }
... } ...}
android { defaultConfig { jackOptions { enabled true jackInProcess true } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 }
... } ...}
Jack and Jill
...:generateReleaseSources:jillReleasePackagedLibraries:jillReleaseRuntimeLibraries:processReleaseJavaRes UP-TO-DATE:transformResourcesWithMergeJavaResForRelease:compileReleaseJavaWithJack:compileReleaseNdk UP-TO-DATE:compileReleaseSources...
...:generateReleaseSources:jillReleasePackagedLibraries:jillReleaseRuntimeLibraries:processReleaseJavaRes UP-TO-DATE:transformResourcesWithMergeJavaResForRelease:compileReleaseJavaWithJack:compileReleaseNdk UP-TO-DATE:compileReleaseSources...
com.android.tools.build:gradle:2.1.0 alpha1
Android build process
Java bytecode(.class)
Libraries(.class)
Dx
JavacSource code
(.java)
Libraries(.class)
XML resources(.xml)
Assets Assets
CompiledXML resources
(.xml)Aapt
Dalvik bytecode(classes.dex)
Androidruntime stubs
(.class)
Transform API
Java bytecode(.class)
Processor
Libraries(.class)
TransformedJava bytecode
(.class)Dx
Javac
Assets
CompiledXML resources
(.xml)Aapt
Dalvik bytecode(classes.dex)
Source code(.java)
Libraries(.class)
XML resources(.xml)
Assets
Runtime stubs(.class)
ProGuard
Java bytecode(.class)
ProGuard
Libraries(.class)
OptimizedJava bytecode
(.class)Dx
Javac
Assets
CompiledXML resources
(.xml)Aapt
Dalvik bytecode(classes.dex)
ProGuardconfig(.txt)
ProGuardmapping
(.txt)
Source code(.java)
Libraries(.class)
XML resources(.xml)
Assets
Runtime stubs(.class)
ProGuard
Java bytecode(.class)
ProGuard
Libraries(.class)
OptimizedJava bytecode
(.class)Dx
Javac
Assets
CompiledXML resources
(.xml)Aapt
Dalvik bytecode(classes.dex)
ProGuardconfig(.txt)
ProGuardmapping
(.txt)
Source code(.java)
Libraries(.class)
XML resources(.xml)
Assets
Runtime stubs(.class)
Jack and Jill
Libraries(.jayce)
Jack
Assets
CompiledXML resources
(.xml)Aapt
Dalvik bytecode(classes.dex)
ProGuardconfig(.txt)
ProGuardmapping
(.txt)
Source code(.java)
Libraries(.class)
XML resources(.xml)
Assets
Runtime stubs(.class)
Jill
Jill Runtime(.jayce)
Code representations
for (int i = 0; i < 8; i++) ...for (int i = 0; i < 8; i++) ...
iconst 0istore v0iload v0bipush 8ificmpge +12...iinc v0, 1goto -12
iconst 0istore v0iload v0bipush 8ificmpge +12...iinc v0, 1goto -12
.class .dex
.java
Javac
Dx
const/4 v0, #0const/16 v1, #8if-ge v0, v1, 8 ...add-int/lit8 v0, v0, #1goto -9
const/4 v0, #0const/16 v1, #8if-ge v0, v1, 8 ...add-int/lit8 v0, v0, #1goto -9
Code representations
for (int i = 0; i < 8; i++) ...for (int i = 0; i < 8; i++) ...
iconst 0istore v0iload v0bipush 8ificmpge +12...iinc v0, 1goto -12
iconst 0istore v0iload v0bipush 8ificmpge +12...iinc v0, 1goto -12
.class .dex
.java
Javac
Efficient to store and executeInconvenient to process
Dx
const/4 v0, #0const/16 v1, #8if-ge v0, v1, 8 ...add-int/lit8 v0, v0, #1goto -9
const/4 v0, #0const/16 v1, #8if-ge v0, v1, 8 ...add-int/lit8 v0, v0, #1goto -9
LOCAL int n
FOR_STATEMENT:- EXPRESSION_STATEMENT: - ASG_OPERATION: - LOCAL_REF i - INT_LITERAL 0- LT_OPERATION: - LOCAL_REF i - INT_LITERAL 8- POSTFIX_INC_OPERATION: - LOCAL_REF i- ...
LOCAL int n
FOR_STATEMENT:- EXPRESSION_STATEMENT: - ASG_OPERATION: - LOCAL_REF i - INT_LITERAL 0- LT_OPERATION: - LOCAL_REF i - INT_LITERAL 8- POSTFIX_INC_OPERATION: - LOCAL_REF i- ...
Code representations
for (int i = 0; i < 8; i++) ...for (int i = 0; i < 8; i++) ...
iconst 0istore v0iload v0bipush 8ificmpge +12...iinc v0, 1goto -12
iconst 0istore v0iload v0bipush 8ificmpge +12...iinc v0, 1goto -12
.class .dex
.java
Javac
.jayce
Jack
const/4 v0, #0const/16 v1, #8if-ge v0, v1, 8 ...add-int/lit8 v0, v0, #1goto -9
const/4 v0, #0const/16 v1, #8if-ge v0, v1, 8 ...add-int/lit8 v0, v0, #1goto -9
Jill
Jack
Implications of Jack and Jill
● Java annotation processors – supported in JackE.g. Dagger, Butterknife
● Bytecode processors – only supported via JillE.g. JaCoCo, Retrolambda
● Other JVM languages – only supported via JillE.g. Scala, Groovy, Dart
● Instant Run – not supported yet
Implications of Jack and Jill
Libraries(.jayce)
Jack
Assets
CompiledXML resources
(.xml)Aapt
Dalvik bytecode(classes.dex)
Javac annotation processorsE.g. Dagger, Butterknife
Source code(.scala,...)
Libraries(.class)
XML resources(.xml)
Assets
Runtime(.class)
Jill
Jill Runtime(.jayce)
Bytecode processors
Java bytecode(.class)Scalac
Application(.jayce)Jill
Java 8: closures.....button.setOnClickListener(view -> .....);.....
.....button.setOnClickListener(view -> .....);.....
.....button.setOnClickListener(new MyActivity$LambdaImpl());.....
.....button.setOnClickListener(new MyActivity$LambdaImpl());.....
public class MyActivity$LambdaImpl {
public void onClick(View view) { ..... }}
public class MyActivity$LambdaImpl {
public void onClick(View view) { ..... }}
Jack
For all versionsof Android
Device
More changes!
RunDalvik bytecode(classes.dex)
Source code(.java)
Libraries(.class)
Runtime stubs(.class)
Build Dalvik bytecode(classes.oat)
AndroidruntimeJack & Jill
OpenJDK
RunDalvik bytecode(classes.dex)
Source code(.java)
Libraries(.class)
Build Dalvik bytecode(classes.oat)
Android +OpenJDKruntime
Android +OpenJDK
runtime stubs(.class)
OpenJDK
Device
OpenJDK
Java 8: default methods
● In your own code:
● In the Android runtime:
public interface java.util.List<E> extends java.util.Collection<E> { public abstract int size(); ... public default void sort(java.util.Comparator<? super E>) { ..... }}
public interface java.util.List<E> extends java.util.Collection<E> { public abstract int size(); ... public default void sort(java.util.Comparator<? super E>) { ..... }}
public interface Foo { public abstract void someMethod();
public void someDefaultMethod() { .... }}
public interface Foo { public abstract void someMethod();
public void someDefaultMethod() { .... }}
Only onAndroid N
New instructions
Dalvik bytecode
RunDalvik bytecode(classes.dex)
Source code(.java)
Libraries(.class)
Build Dalvik bytecode(classes.oat)
Android +OpenJDKruntime
Android +OpenJDK
runtime stubs(.class)
New instructions
Device
Java 8: closures
.....
● put-field-lambda● get-field-lambda● put-static-lambda● get-static-lambda● aget-lambda● aput-lambda● move-lambda● cmp-lambda● return-lambda
.....
● put-field-lambda● get-field-lambda● put-static-lambda● get-static-lambda● aget-lambda● aput-lambda● move-lambda● cmp-lambda● return-lambda Only on
Android N+
New Dalvik instructions:
Build performance 44s – Javac + dx (clean build)
1m9s – Javac + ProGuard optimize + dx (clean build)
24s – Javac + DexGuard (clean build)
2m36s – Javac + DexGuard optimize (clean build)
1m17s – Jack (clean build)
47s – Jack (clear all dex files)
15s – Javac + dx (clear all class files) 15s – Javac + dx (clear all class files)
5s – Javac + dx (clear one class file) 5s – Javac + dx (clear one class file)
2s – Javac + dx (code unchanged) 2s – Javac + dx (code unchanged)
40s – Jack (clear one dex file) 40s – Jack (clear one dex file)
3s – Jack (code unchanged) 3s – Jack (code unchanged)
Google I/O app
(AMD A10-7800, Ubuntu 14.04, Java 8, Android Gradle 2.1.0 alpha1, Gradle daemon)
49s – Jack minify (clear all dex files) 49s – Jack minify (clear all dex files)
21s – Javac + ProGuard + dx (clean build) 21s – Javac + ProGuard + dx (clean build)
Application runtime performance
50,000 – Javac + dx
63,800 – Javac + ProGuard optimize + dx
82,300 – Javac + DexGuard optimize
54,500 – Jack
Caffeinemark benchmark
(Nexus 5, Android 6.0, ART)
+9%
+28%
+65%
(higher is better)
Application size
3.1M – Javac + dx
1.9M – Javac + ProGuard optimize + dx
1.8M – Javac + DexGuard optimize
1.9M – Jack + minify
Google I/O app
-39%
-38%
-44%
(smaller is better)
DexGuard
Java bytecode(.class)
DexGuard
Libraries(.class)
Javac
Optimizedassets
OptimizedXML resources
(.xml)Aapt
OptimizedDalvik bytecode
(classes.dex)
ProGuardconfig(.txt)
ProGuardmapping
(.txt)
Source code(.java)
Libraries(.class)
XML resources(.xml)
Assets
Androidruntime stubs
(.class)
CompiledXML resources
(.xml)
Androidruntime stubs
(.class)
Assets
Native code(.so)Clang
Source code(.c / .cpp)
Optimizednative code
(.so)
Conclusions
● Huge changes● Clean implementation
● Different build process● New intermediary representation
Internally
For languages and tools
Conclusions
● Huge changes● Clean implementation
● More efficient builds● Java 8
● Different build process● New intermediary representation
Internally
For languages and tools
For app developers
Further reading
● “Experimental New Android Tool Chain - Jack and Jill”http://tools.android.com/tech-docs/jackandjill
● “Java 8 Language Features”https://developer.android.com/preview/j8-jack.html
● “Jack (Java Android Compiler Kit)”https://source.android.com/source/jack.html
● AOSP repositoryhttps://android.googlesource.com/toolchain/jack/
● “State of the ART”http://androidbackstage.blogspot.com/2016/03/episode-45-state-of-art.html