在 Android 8.0 版本中,Android Runtime (ART) 有了极大改进,使用 @FastNative 和 @CriticalNative 注解可以更快速地对 Java 原生接口 (JNI) 进行原生调用。这些内置的 ART 运行时优化可以加快 JNI 转换速度,并取代了现已弃用的 !bang JNI 标记。这些注解对非原生方法没有任何影响,并且仅适用于 bootclasspath
上的平台 Java 语言代码(无 Play 商店更新)。
@FastNative
注解支持非静态方法。如果某种方法将 jobject
作为参数或返回值进行访问,请使用此注解。
利用 @CriticalNative
注解,可更快速地运行原生方法,但存在以下限制:
- 方法必须是静态方法 - 没有参数、返回值或隐式
this
的对象。 - 仅将基元类型传递给原生方法。
- 原生方法在其函数定义中不使用
JNIEnv
和jclass
参数。 - 方法必须使用
RegisterNatives
进行注册,而不是依靠动态 JNI 链接。
@FastNative
和 @CriticalNative
注解在执行原生方法时会停用垃圾回收。不要与长时间运行的方法一起使用,包括通常很快但一般不受限制的方法。
停顿垃圾回收可能会导致死锁。如果锁尚未得到本地释放(即尚未返回受管理代码),请勿在原生快速调用期间获取锁。此要求不适用于常规的 JNI 调用,因为 ART 将正执行的原生代码视为已暂停的状态。
@FastNative
可以使原生方法的性能提升高达 3 倍,而 @CriticalNative
可以使原生方法的性能提升高达 5 倍。例如,在 Nexus 6P 设备上测量的 JNI 转换如下:
Java 原生接口 (JNI) 调用 | 执行时间(以纳秒计) |
---|---|
常规 JNI | 115 |
!bang JNI | 60 |
@FastNative | 35 |
@CriticalNative | 25 |