是什么让JNI呼叫变慢?

pde*_*eva 184 java performance java-native-interface

我知道在Java中进行JNI调用时"跨越边界"很慢.

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

And*_*mas 169

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

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

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

一些额外的讨论,可能是过时的,可以在2000年由Steve Wilson和Jeff Kesselman在"9.2:检查JNI成本"一节中的"Java?Platform Performance:Strategies and Tactics"中找到.这是关于的一路下跌三分之一此页由以下@Philip在评论规定.

2009年IBM developerWorks文章"使用Java Native Interface的最佳实践"提供了一些有关避免JNI性能缺陷的建议.

  • 该答案指出,一些标准的本机代码在JVM中内联而不是使用JNI.上面,"本机方法"是指通过JNI实现的用户定义本机方法的一般情况.感谢指向sun.misc.Unsafe的指针. (5认同)
  • @AH,你错误的内在w/JNI.他们是完全不同的.`sun.misc.Unsafe`和很多其他的东西,如`System.currentTimeMillis/nanoTime`,由JVM通过'magic'处理.它们不是JNI,它们根本没有正确的.c/.h文件,它们本身就是JVM impl.除非您正在编写/攻击JVM,否则无法遵循该方法. (3认同)

Tem*_*ema 24

值得一提的是,并非所有标记的Java方法native都"慢".其中一些是内在函数,使它们非常快.要检查哪些是内在的以及哪些不是内在的,您可以do_intrinsicvmSymbols.hpp中查找.


dmc*_*mck 22

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

本文概述了更多细节

如果您对JNI与本机代码的基准测试感兴趣,那么该项目具有运行基准测试的代码.

  • 这篇论文是关于Java 1.3的 - 很久以前.当时的问题是否仍然适用于Java 7? (13认同)
  • 您链接到的纸张似乎更像是一个性能基准测试纸,而不是描述JNI内部工作方式的纸张. (2认同)