在Android 4.4系统,大家都开始推出新的Android运行时,ART。这种运行提供了许多可提高性能和Android平台和应用的平滑新功能。 (您可以找到有关介绍造型艺术的新功能的更多信息。)
目前,ART可在许多Android 4.4系统的设备,如Nexus的4,5的Nexus,Nexus 7和谷歌Play版设备。这时,所有的设备仍然使用的Dalvik作为默认运行。我们鼓励您测试您的应用程序的兼容性ART并利用艺术的新功能。然而,就目前而言,你也应该小心保持与Dalvik的兼容性。
本文档可以让你知道的事情看迁移现有的应用程序时要与ART兼容的。艺术运行时,大多数应用程序应该只是工作。然而,一些技术,对Dalvik的工作,不要艺术作品。本文讨论的一些问题。
解决垃圾回收(GC)问题
在Dalvik的,经常应用发现它很有用显式调用System.gc()的提示垃圾回收(GC)。这应该是远远艺术没有那么必要,特别是如果你调用垃圾收集,以防止GC_FOR_ALLOC型发生或减少碎片。可以验证其运行正由调用System.getProperty(“java.vm.version”)。如果艺术是在使用中,该属性的值为“2.0.0”或更高。
此外,压缩垃圾收集器是根据在Android开源项目(AOSP)的开发,以提高内存管理。正因为如此,你应该避免使用与压实GC(如保存指向对象实例的数据)不兼容的技术。这是一个应用程序,使用Java本地接口(JNI)显得尤为重要。有关详细信息,请参阅防止JNI问题。
防止JNI问题
ART的JNI比的Dalvik的有点严格。它是用CheckJNI模式捕捉常见的问题一个特别好的主意。如果您的应用程序利用了C / C ++代码,你应该阅读以下文章:
Android的调试用JNI CheckJNI
垃圾收集问题检查JNI代码
艺术有一个正在开发的压缩垃圾收集器在Android开源项目(AOSP)。一旦压缩垃圾收集器在使用时,对象可能在存储器移动。如果使用C / C ++代码,不执行与压实GC不兼容的操作。我们加强CheckJNI确定一些潜在的问题(如在ICS JNI本地参考更改说明)。
特别是观看一个领域是使用get ... ArrayElements()和Release ... ArrayElements()函数。在与非压缩GC运行时间,获取... ArrayElements()函数通常返回实际内存支持数组对象的引用。如果你更改了返回数组的元素之一,数组对象本身改变(与参数释放... ArrayElements()通常忽略)。然而,如果压缩的GC是在使用中,获取... ArrayElements()函数可能返回存储器的副本。如果你滥用的参考,当压缩GC在使用中,这可能会导致内存损坏或其他问题。例如:
如果您对返回数组的元素进行任何更改,必须调用相应的释放... ArrayElements()函数,当你完成,以确保您所做的更改正确复制到底层数组对象。
当你释放内存数组元素,必须使用相应的模式,这取决于你所做的修改:
如果你没有做数组元素的任何变化,使用JNI_ABORT模式,它释放内存,而不复制变回为基础数组对象。
如果你修改了阵列,并且不需要参考任何更多,使用代码0(更新数组对象并释放内存的复印件)。
如果更改到您要提交阵列,并且要保留数组的副本,请使用JNI_COMMIT(其中更新底层数组对象并保留复印件)。
当你调用Release ... ArrayElements(),返回最初是由Get ... ArrayElements返回相同的指针()。例如,它不是安全递增原来的指针(通过返回数组的元素扫描),然后传递递增的指针,以释放... ArrayElements()。通过这项修改指针可能会导致被释放错误的内存,导致内存损坏。
错误处理
ART的JNI抛出的数,其中的Dalvik没有的情况下错误。 (再次,你可以通过CheckJNI测试赶上很多这样的情况。)
例如,如果RegisterNatives被调用的方法,其不存在(也许是因为通过一工具如ProGuard的除去方法),ART现在正确抛出的NoSuchMethodError:
08-12 17:09:41.082 13823 13823 E AndroidRuntime: FATAL EXCEPTION: main 08-12 17:09:41.082 13823 13823 E AndroidRuntime: java.lang.NoSuchMethodError: no static or non-static method "Lcom/foo/Bar;.native_frob(Ljava/lang/String;)I" 08-12 17:09:41.082 13823 13823 E AndroidRuntime: at java.lang.Runtime.nativeLoad(Native Method) 08-12 17:09:41.082 13823 13823 E AndroidRuntime: at java.lang.Runtime.doLoad(Runtime.java:421) 08-12 17:09:41.082 13823 13823 E AndroidRuntime: at java.lang.Runtime.loadLibrary(Runtime.java:362) 08-12 17:09:41.082 13823 13823 E AndroidRuntime: at java.lang.System.loadLibrary(System.java:526)ART还记录如果RegisterNatives被称为没有方法的错误(logcat中可见):
W/art ( 1234): JNI RegisterNativeMethods: attempt to register 0 native methods for <classname>此外,JNI函数GetFieldID()和GetStaticFieldID()现在可以正确地抛出简单地返回null NoSuchFieldError代替。同样,的GetMethodID()和GetStaticMethodID()现在可以正确地抛出的NoSuchMethodError。这可能会导致被抛出来的原生代码的Java调用方,因为未处理的异常或异常CheckJNI故障。这使得它特别重要的与CheckJNI模式下测试技术兼容的应用程序。
F/art: art/runtime/thread.cc:435] Attempt to attach a thread with a too-small stack (16384 bytes)对象模型更改
Before Android 4.1, method void com.foo.Bar.quux() would have incorrectly overridden the package-private method in com.quux.Quux如果您打算在不同的包来覆盖类的方法,申报方法公开或保护。
Class.getSuperclass() == java.lang.Object.class而不是继续,直到该方法返回null。