是什么让 JNI 调用速度变慢?

2022-08-31 06:06:24

我知道在Java中进行JNI调用时“跨越边界”是很慢的。

但是,我想知道是什么让它变慢?当进行JNI调用使其如此缓慢时,底层jvm实现会做什么?


答案 1

首先,值得注意的是,通过“慢”,我们谈论的是可能需要几十纳秒的东西。对于微不足道的本机方法,在2010年,我测量了Windows桌面上的平均40 ns和Mac桌面上的11 ns的调用。除非你打了很多电话,否则你不会注意到。

也就是说,调用本机方法可能比进行普通的 Java 方法调用。原因包括:

  • 本机方法不会由 JVM 内联。它们也不会为这台特定的机器进行及时编译 - 它们已经编译好了。
  • 可以在本机代码中复制 Java 数组以供访问,然后复制回来。成本可以与阵列的大小成线性关系。我测量了一个 100,000 个数组的 JNI 复制,在我的 Windows 桌面上平均约为 75 微秒,在 Mac 上为 82 微秒。
  • 如果该方法传递了一个对象,或者需要进行回调,那么本机方法可能会对 JVM 进行自己的调用。从本机代码访问 Java 字段、方法和类型需要类似于反射的内容。签名以字符串形式指定,并从 JVM 查询。这既慢容易出错。
  • Java 字符串是对象,具有长度和编码。访问或创建字符串可能需要 O(n) 副本。

一些额外的讨论,可能过时的,可以在Steve Wilson和Jeff Kesselman的“Java(tm)平台性能:战略和战术”中找到,在2000年,在“9.2:检查JNI成本”一节中。它大约是本页下方的三分之一,在下面@Philip的评论中提供。

2009 年 IBM developerWorks 的论文“使用 Java Native Interface 的最佳实践”提供了一些关于避免 JNI 性能缺陷的建议。


答案 2

值得一提的是,并非所有标有“慢速”的Java方法。其中一些是使它们非常快的内在因素。要检查哪些是固有的,哪些不是,您可以在vmSymbols.hpp中查找。nativedo_intrinsic


推荐