调用本机方法时JVM必须做什么?

时间:2014-07-14 22:03:47

标签: java jvm java-native-interface

在调用声明为native的Java方法时,JVM运行时必须执行哪些常规步骤?

HotSpot 1.8.0 JVM如何实现JNI函数调用?涉及哪些检查步骤(例如返回后未处理的异常?),JVM要执行哪些簿记(例如本地参考注册表?),以及在调用本机Java方法后控制在哪里?如果有人可以提供原生HotSpot 1.8.0代码中的入口点或重要方法,我也将不胜感激。

免责声明:我知道我可以自己阅读代码,但事先的解释有助于快速找到我的代码。此外,我发现这个问题值得谷歌搜索。 ;)

1 个答案:

答案 0 :(得分:35)

与简单的C函数调用相比,从Java调用JNI方法相当昂贵。 HotSpot通常执行以下大多数步骤来调用JNI方法:

  1. 创建堆栈框架。
  2. 根据ABI将参数移动到正确的寄存器或堆栈位置。
  3. 将对象引用包装到JNI句柄。
  4. 获取静态方法的JNIEnv*jclass,并将其作为附加参数传递。
  5. 检查是否应调用method_entry跟踪功能。
  6. 如果方法为synchronized,则锁定对象监视器。
  7. 检查本机功能是否已链接。函数查找和链接是懒惰地执行的。
  8. 将线程从in_java切换到in_native州。
  9. 调用原生函数
  10. 检查是否需要安全点。
  11. 将线程返回in_java州。
  12. 如果锁定,请解锁显示器。
  13. 通知method_exit
  14. 解包对象结果并重置JNI句柄块。
  15. 处理JNI例外情况。
  16. 移除堆栈框架。
  17. 此程序的源代码可在SharedRuntime::generate_native_wrapper找到。

    如您所见,开销可能很大。但在许多情况下,上述大部分步骤都不是必需的。例如,如果本机方法只对字节数组执行某些编码/解码,并且不抛出任何异常,也不会调用其他JNI函数。对于这些情况,HotSpot有一个名为Critical Natives的非标准(并且未知)约定,讨论了here