与简单的C函数调用相比,从Java调用JNI方法非常昂贵。HotSpot通常执行以下大多数步骤来调用JNI方法:
- 创建一个堆栈框架。
- 根据ABI将参数移至正确的寄存器或堆栈位置。
- 将对象引用包装到JNI句柄。
- 获取
JNIEnv*
并jclass
获取静态方法,并将其作为附加参数传递。 - 检查是否应调用
method_entry
跟踪功能。 - 如果方法为,则锁定对象监视器
synchronized
。 - 检查本机功能是否已链接。功能查找和链接是延迟执行的。
- 将线程从切换
in_java
到in_native
状态。 - 调用本机函数
- 检查是否需要安全点。
- 使线程返回
in_java
状态。 - 如果锁定,则解锁监视器。
- 通知
method_exit
。 - 解开对象结果并重置JNI句柄块。
- 处理JNI异常。
- 卸下堆栈框架。
该过程的源代码可以在SharedRuntime ::
generate_native_wrapper中找到。
如您所见,开销可能很大。但是在许多情况下,上述大多数步骤都是不必要的。例如,如果本机方法仅对字节数组执行一些编码/解码,并且不引发任何异常,也不调用其他JNI函数。对于这些情况,HotSpot具有称为的非标准(且未知)约定
CriticalNatives



