Platform Architecture
The Linux Kernel:安卓平台依赖于Linux内核,使用到了线程和内存管理等基础功能,同时充分利用了Linux的安全特性,允许设备制造商对熟知的内核开发硬件驱动。
Hardware Abstraction Layer (HAL):硬件抽象层对上层Java API framework暴露了标准的设备接口,HAL层由各种Library库组成,每种库实现一种硬件设备的接口,比如相机或者蓝牙,当framework API需要访问硬件时,系统会自动加载对应的Library库。
Android Runtime:系统5.0(API21)之前使用的是Dalvik虚拟机,5.0之后Runtime使用的是ART虚拟机,主要特点包括AOT/JIT、优化的GC垃圾回收、更好地支持调试功能。ART完全兼容Dalvik,反过来不一定。
Native C/C++ Libraries:安卓系统的核心组件,例如ART/HAL都是基于C/C++的Native库实现,对上层暴露的是Java接口,所以应用可以依赖这些Java接口开发,也可以直接NDK开发。
Java API Framework:安卓系统的特性集合以Java API的形式对外提供,简化了系统核心模块的使用,包括:View System、Resource Manager、Notification Manager、Activity Manager、Content Provider,开发者可以访问完整/一致的framework API。
System Apps:系统自带了一些应用,和普通应用没什么区别(除了类似设置的应用),用户可以再次安装第三方的应用,并选作默认。
1. Use Java 8 Language Features
安卓支持所有的Java7语言特性,支持部分Java8的特性。为了支持Java8的语言特性,需要使用新的Jack编译工具链,在 >=Android Studio 2.1 版本上可用。
可支持的Java8语言特性:
- Default and static interface methods
- Lambda expressions
- Repeatable annotations
- Method References
-
Jack工具链用于替换现有工具链,集成了包括repackagin, shrinking, obfuscation, multidex工具链环节,使用自定义的.jack字节码格式替换.class格式,对比生成dex的过程:
- javac(.java->.class) -> dx(.class->.dex)
jack(.java->.jack->.dex)
Jack工具链还不完善,持续改进中。
2. Verifying App Behavior on the Android Runtime (ART)
大部分App都能直接从Dalvik上迁移到ART,有一小部分操作存在区别:
Addressing Garbage Collection (GC) Issues:在Dalvik上可以显式地调用System.gc()触发垃圾回收,ART使用了compacting垃圾回收器,没有必要做这个操作,特别是为了GC_FOR_ALLOC类型的或者减少内存碎片的目的,可以通过System.getProperty(“java.vm.version”) >= “2.0.0”判断虚拟机版本。
ART’s JNI检查比Dalvik更严格,最好使用CheckJNI模式检查常见的问题。
Checking JNI code for garbage-collection issues:ART使用AOSP(Android Open Source Project)项目的compacting garbage collector垃圾回收器,在这种情况下对象在内存中可能被移动,使用CheckJNI工具可以检查不兼容的操作和隐藏问题。
使用Get…ArrayElements()和Release…ArrayElements()时,对于non-compacting GC,Get…ArrayElements()方法返回真实的内存对象引用,对返回数据元素的修改会直接修改到原始对象,对应的Release…ArrayElements操作会被忽略,但是compacting GC对于Release的操作不同,需要使用不同模式的Release:1.没有修改数组元素使用code=JNI_ABORT; 2.修改了数组元素但不再需要引用使用code=0; 3.修改了数组元素且需要继续引用数组使用code=JNI_COMMIT。
Error handling:ART’s JNI相比Dalvik会抛出更多类型的错误,比如RegisterNatives遇到方法不存在会抛出NoSuchMethodError,同时向logcat写日志,GetFieldID()/GetStaticFieldID()遇到成员不存在会抛出NoSuchFieldError错误而不是Dalvik直接返回null,同理GetMethodID()/GetStaticMethodID()。ART假定用户调用CallNonvirtual…Method()方法是调用当前类的方法,而不是子类。
Preventing Stack Size Issues:Dalvik对native和java使用分开的栈,Java默认32KB/Native默认1MB,ART的Java和Native使用同一个栈。
Object model changes:Dalvik错误地允许用户override包内访问权限的package-private方法,在ART中会生成一个warning(Before Android 4.1, method void com.foo.Bar.quux() would have incorrectly overridden the package-private method in com.quux.Quux),但是为了兼容Dalvik还是可以运行。
相比Dalvik,ART的Object方法包含private成员,如果要反射类继承体系中的成员,最顶级的类判断可以是 Class.getSuperclass() == java.lang.Object.class。
Proxy InvocationHandler.invoke()现在对于无参函数允许接收null作为参数,在Dalvik中代理调用无参方法必须传入空数组。
Fixing AOT Compilation Issues:AOT编译功能由dex2oat工具执行。ART verifier会对一些典型问题进行标记:invalid control flow, unbalanced moniterenter/moniterexit, 0-length parameter type list size。