為什麼method數超過65535會build fail?
TRANSCRIPT
Why MultiDex?● Single Dex methods over 65535 will cause
“Conversion to Dalvik format failed” at build time○ Dalvik uses 16bits to index mehtods
● Single Dex file size >5MB will cause INSTALL_FAILED_DEXOPT before Android 2.3 at runtime○ Dalvik linearAlloc size is 5MB in Android 2.2 and 2.3
What is Dex file?Programs are commonly written in Java and compiled to bytecode for the Java virtual machine, which is then translated to Dalvik bytecode and stored in .dex (Dalvik EXecutable).
How to apply it? (Cont.)2. Modify your Application class to extend MultidexApplication
public class MobileDubaApplication extends MultiDexApplication {@Overrideprotected void attachBaseContext(final Context base) {
super.attachBaseContext(base);}
@Overridepublic void onCreate() {
} }
public class MultiDexApplication extends Application { @Override
protected void attachBaseContext(Context base) {super.attachBaseContext(base);MultiDex.install(this);
} }
Quiz - Application啟動順序?
A. Application.onCreate()
B. ActivityThread.installProviders()
C. Application.attachBaseContext()
1. __________________________
2. __________________________
3. __________________________
What’s the secret?
1. How class loader works2. How to load class from dex file3. MultiDex Install load dex flow
BaseDexClassLoader load dex flow1. BaseDexClassLoader uses makeDexElement
to load dex2. dexElement is a list of dex/resource (class
path) elements
MultiDex install load dex flow1. Call DexPathList$makeDexElement() by
reflection to force Dalvik loads dex files2. Get dexElements by reflection and write back
extra elements by System.arraycopy()
Our Goal● Smaller → Lzma secondary dex and
concurrent decompress it before install to reduce APK size
● Faster → Concurrent install dex to reduce cold launch time
● Nicer → Show splash activity at the very first launch time and defer install dex process to worker thread
Demo - Launch CMS on low-end phone
Before After
Lzma dex - Modify Gradle Build Configuration
1. Unpack Proguarded jar to get class files2. Split class files into main-dex and sub-dexs.3. Generate dex file from class file by “dx” build tool4. Lzma sub-dex file
5. Add lzma files into resocure file
⇒ Looks like the class is either missing or broken when it was used
⇒ 我的觀察拉
⇒ But why? We have to trace into Dalvik native code to figure it out
<clinit> & <init>● <clinit> are the static initialization blocks for the class,
and static field initialization● <init> is the (or one of the) constructor(s) for the
instance, and non-static field initialization.
dvmInitClass● dvmInitClass will be called when the <clinit> code
resolves one of its fields, the field resolution will try to initialize the class.○ dvmInitClass is executing before <clinit>
● dvmInitClass tries to verify every methods in the class○ All classes in method’s parameter type, return type or
called by method will be resolved○ If the class can’t be resolved, Dalvik will throw
ClassNotFoundException or NoClassDefFoundError when the class was access
Remove dependencies from Application- Proxy Pattern● Move complex logic from Application to
ApplicationProxy○ Make sure all classes in subdex will not be resolved
when Dalvik initial Application class