Android4.4开始android的运行时出现了ART选项,以前只有Dalvik,也就是说android系统的虚拟机可以选择 Dalvik 也可以选择 ART,选择虚拟机的设置在 Developer options/Select Runtime 中完成
设置虚拟机的选项本质上只是改变一个系统属性的值,这个属性是 persist.sys.dalvik.vm.lib
app_process会创建android系统的第一个虚拟机。对于android系统的应用层和android系统的应用框架层来说,它们只知道有一个“虚拟机”,但是它们不需要知道这个虚拟机是ART还是Dalvik.
在app_process 创建虚拟机的过程中,libnativehelper 决定创建虚拟机的类型,具体的代码在libnativehelper/JniInvocation.cpp 中, 它根据persist.sys.dalvik.vm.lib 的值来决定是链接到libart.so 还是 libdvm.so.
如果选择ART的模式,在创建ART虚拟机的过程中会对framework 中的jar包进行 dex2oat,也就是 将framework 中的jar包 编译成 oat文件。在这个编译的过程中,虚拟机还没有处于运行的状态,如果编译的过程中 类的static{} 块和static 变量的初始化中存在 调用 native 的代码,那么会导致 dex2oat出现错误,系统无法正常启动,出现的log 一般如下所示
F/dex2oat ( 473): art/runtime/interpreter/interpreter.cc:223] Attempt to invoke native method in non-started runtime: boolean android.os.SystemProperties.native_get_boolean(java.lang.String, boolean)
F/dex2oat ( 473): art/runtime/runtime.cc:203] Runtime aborting...
F/dex2oat ( 473): art/runtime/runtime.cc:203] Aborting thread:
F/dex2oat ( 473): art/runtime/runtime.cc:203] "main" prio=5 tid=1 Runnable (still starting up)
F/dex2oat ( 473): art/runtime/runtime.cc:203] | group="" sCount=0 dsCount=0 obj=0x00000000 self=0x41ea9100
F/dex2oat ( 473): art/runtime/runtime.cc:203] | sysTid=473 nice=0 cgrp=default sched=0/0 handle=0x4009d154
F/dex2oat ( 473): art/runtime/runtime.cc:203] | state=R schedstat=( 18648884604 1281988401 114503 ) utm=1202 stm=662 core=3 HZ=100
F/dex2oat ( 473): art/runtime/runtime.cc:203] | stack=0xbe3b5000-0xbe3b9000 stackSize=8MB
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: art::Thread::DumpStack(std::ostream&) const+87 [0x403f4edc] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: ??? [0x403ed06c] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: art::Runtime::Abort()+79 [0x403ed5fc] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: art::LogMessage::~LogMessage()+505 [0x4029a93a] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: ??? [0x4031c4fc] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: artInterpreterToInterpreterBridge+307 [0x4032c140] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: ??? [0x4032c750] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: ??? [0x4032e5b6] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: ??? [0x40331bc2] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: art::interpreter::EnterInterpreterFromInvoke(art::Thread*, art::mirror::ArtMethod*, art::mirror::Object*, unsigned int*, art::JValue*)+603 [0x40338884] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: art::ClassLinker::InitializeClass(art::mirror::Class*, bool, bool)+1947 [0x402c3f70] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: art::ClassLinker::EnsureInitialized(art::mirror::Class*, bool, bool)+33 [0x402c415a] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: artInterpreterToInterpreterBridge+169 [0x4032c0b6] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: ??? [0x4032c750] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: ??? [0x4032e5b6] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: ??? [0x40331bc2] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: artInterpreterToInterpreterBridge+193 [0x4032c0ce] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: ??? [0x4032c750] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: ??? [0x4032e5b6] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: ??? [0x40331bc2] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: artInterpreterToInterpreterBridge+193 [0x4032c0ce] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: ??? [0x4032c750] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: ??? [0x4032cf28] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: ??? [0x403312ee] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: artInterpreterToInterpreterBridge+193 [0x4032c0ce] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: ??? [0x4032c750] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: ??? [0x4032da98] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: ??? [0x4033116a] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: art::interpreter::EnterInterpreterFromInvoke(art::Thread*, art::mirror::ArtMethod*, art::mirror::Object*, unsigned int*, art::JValue*)+603 [0x40338884] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: art::ClassLinker::InitializeClass(art::mirror::Class*, bool, bool)+1947 [0x402c3f70] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: art::ClassLinker::EnsureInitialized(art::mirror::Class*, bool, bool)+33 [0x402c415a] (libart.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] native: ??? [0x401ea69c] (libart-compiler.so)
F/dex2oat ( 473): art/runtime/runtime.cc:203] at android.os.SystemProperties.native_get_boolean(Native method)
F/dex2oat ( 473): art/runtime/runtime.cc:203] at android.os.SystemProperties.
(SystemProperties.java:39)
F/dex2oat ( 473): art/runtime/runtime.cc:203] - locked <0x42f71e88> (a java.lang.Class)
F/dex2oat ( 473): art/runtime/runtime.cc:203] at android.content.res.Configuration$Injector.setDefaultFontScale(Configuration.java:58)
F/dex2oat ( 473): art/runtime/runtime.cc:203] at android.content.res.Configuration.setToDefaults(Configuration.java:851)
F/dex2oat ( 473): art/runtime/runtime.cc:203] at android.content.res.Configuration.(Configuration.java:643)
F/dex2oat ( 473): art/runtime/runtime.cc:203] at android.content.res.Configuration.(Configuration.java:95)
F/dex2oat ( 473): art/runtime/runtime.cc:203] - locked <0x42e51070> (a java.lang.Class)
Attempt to invoke native method in non-started runtime 这句话的意思是 没有虚拟机的时候(虚拟机还没有开始运行),native 方法不能被执行。这个问题需要我们注意,为了保证ART模式的正常运行,在修改framework 代码的时候
1. 在类的static 代码块不能 调用 native 方法
2. 在类的static 变量初始化的时候不能调用 native 方法
上述的log 中我们可以看到 是 android.content.res.Configuration的static 代码块中调用了 native 方法 ,所以解决方案就是将 static 代码块中的native 部分修改。