是什么让JNI呼叫变慢?

时间:2011-10-08 18:46:22

标签: java performance java-native-interface

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

但是我想知道是什么让它变慢? 在进行使其速度变慢的JNI调用时,底层的jvm实现会做什么?

3 个答案:

答案 0 :(得分:161)

首先,值得注意的是,通过“慢”,我们谈论的事情可能需要几十纳秒。对于琐碎的原生方法,在2010年,我在Windows桌面上平均测量了40秒的呼叫,在我的Mac桌面上测量了11 ns。除非您正在进行许多电话,否则您将不会注意到。

也就是说,调用本机方法可能比正常的Java方法调用更慢。原因包括:

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

一些额外的讨论,可能是过时的,可以在2000年的“Java?Platform Performance:Strategies and Tactics”中找到,Steve Wilson和Jeff Kesselman在“9.2:检查JNI成本”一节中找到。它大约是this page的三分之一,由@Philip在下面的评论中提供。

2009年IBM developerWorks论文"Best practices for using the Java Native Interface"提供了一些有关避免JNI性能陷阱的建议。

答案 1 :(得分:22)

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

答案 2 :(得分:21)

基本上,JVM解释性地为每个JNI调用构造C参数,并且代码未被优化。

this paper

中列出了更多详细信息

如果您对基准测试JNI与本机代码感兴趣this project具有运行基准测试的代码。