是什么使JNI通话变慢?


194

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

不过,我想知道什么是它,使得它慢?进行JNI调用如此之慢时,底层jvm实现会做什么?


2
(+1)好问题。当我们讨论这个问题时,我想鼓励任何做过实际基准测试的人发表他们的发现。
NPE

2
一个JNI调用需要将传入的Java对象转换为C语言(例如)可以理解的东西。与返回值相同。类型转换和调用堆栈封送处理是其中的一大块。
戴夫·牛顿

戴夫,我了解并以前听说过。但是转换到底是什么样的呢?那是什么“东西”?我正在寻找细节。
pdeva 2011年

使用直接ByteBuffer在Java和C之间传递数据可以导致相对较低的开销。
彼得·劳瑞

6
该调用需要一个适当的C堆栈框架,将所有有用的CPU寄存器压入(并弹出它们),该调用需要隔离,而且它会阻止很多优化,例如内联。此外,线程还必须离开执行堆栈锁(例如,在本机代码中允许有偏向的锁起作用),然后将其取回。
bestsss 2011年

Answers:


174

首先,值得注意的是,“慢”是指可能花费数十纳秒的时间。对于琐碎的本机方法,2010年,我在Windows桌面上测得的呼叫平均时间为40 ns,在Mac桌面上测得的平均呼叫时间为11 ns。除非您打很多电话,否则您不会注意到。

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

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

在Steve Wilson和Jeff Kesselman于2000年出版的“ Java?平台性能:策略和策略”中的“ 9.2:检查JNI成本”部分中,可以找到一些可能过时的附加讨论。大约是此页面下三分之一的位置,在下面@Philip的评论中提供。

2009年IBM developerWorks论文“使用Java本机接口的最佳实践”提供了一些有关避免JNI的性能陷阱的建议。


1
这个答案索赔,一些本地代码可以由JVM内联。
AH

5
该答案指出,某些标准本机代码在JVM中内联,而不是使用JNI。上面的“本机方法”是指通过JNI实现的用户定义本机方法的一般情况。感谢您指向sun.misc.Unsafe的指针。
安迪·托马斯

我不想宣称,这种方法可以用于每个JNI调用。但它不会伤害知道有纯粹的字节码和纯JNI代码之间的一些中间地带。也许这会影响一些设计决策。也许将来会推广这种机制。
AH

3
@AH,您会误解带有JNI的内在函数。他们是完全不同的。JVM还通过“魔术”来处理sun.misc.Unsafe很多其他东西System.currentTimeMillis/nanoTime。它们不是JNI,并且根本没有适当的.c / .h文件,仅是JVM impl本身。除非您正在编写/修改JVM,否则无法遵循该方法。
bestsss 2012年

1
此java.sun.com文档 ”当前已损坏- 是一个有效的链接。
菲利普·古恩2014年

25

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


23

基本上,JVM会为每个JNI调用解释性地构造C参数,并且不会对代码进行优化。

本文概述了更多细节

如果您对基准测试JNI与本机代码感兴趣,则该项目具有用于运行基准测试的代码。


2
您链接到的论文似乎更像是性能基准论文,而不是描述JNI内部工作方式的论文。
pdeva 2011年

@pdeva不幸的是,我发现的其他资源都链接到java.sun.com,并且自从Oracle收购以来,这些链接尚未更新。我正在寻找有关JNI内部的更多详细信息。
dmck,2011年

13
本文是关于Java 1.3的-相当久以前。那时候的问题仍然适用于Java 7吗?
AH
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.