Java JNI调用的数组开销
Possible Duplicate:
What makes JNI calls slow?
首先让我说,这些问题更多地是出于好奇而不是出于真正的需要
我很想知道从Java进行JNI调用,比如说,System.arraycopy
与分配数组和使用for循环复制元素相比,开销是多少
如果开销很大,那么可能有一个粗略的“幻数”元素,它只需使用for循环,而不是使用系统调用,就可以对其进行补偿。另外,系统调用中到底涉及到什么导致了这种开销? 我猜堆栈必须被推到调用的上下文中,这可能需要一段时间,但我找不到对整个过程的好解释
让我澄清我的问题:
我知道使用arraycopy是在Java中复制数组的最快方法
也就是说,假设我用它来复制一个只有一个元素的数组。因为我要调用底层操作系统来实现这一点,在这个调用中有的开销。我很想知道这种开销是什么,以及在通话过程中会发生什么
如果使用arraycopy误导了你,使你偏离了我问题的目的,我很抱歉。我想知道JNI调用的开销,以及实际调用中涉及的内容
# 1 楼答案
你说得对system calls相当贵。然而,{}中的{}有点用词不当。没有涉及系统调用
当你看}
System.arraycopy()
的定义时,它被声明为native
。这意味着该方法是用C++实现的。如果你是这样倾向的,你可以看看JDK的源代码,找到C++函数。在OpenJDK 7中,它被称为JVM_ArrayCopy()
,并生活在hotspot/src/share/vm/prims/jvm.cpp
。实现过程异常复杂,但本质上是一个^{如果
arraycopy()
被用作正常的本机函数,那么调用它会有开销。参数检查等会导致更多开销然而,很可能JIT compiler知道
System.arraycopy()
。这意味着,编译器不知道调用C++函数,而是知道如何生成专门编写的机器代码来执行数组复制。我不知道其他JVM的情况,但HotSpot确实对System.arraycopy()
有这样的“内在”支持如果你的数组很小,你可以用手工制作的循环来击败
System.arraycopy()
。如果在编译时知道循环的大小,可能会做得更好,因为这样也可以展开循环。然而,除了在最狭隘的情况下,所有这些都不是真正相关的# 2 楼答案
System.arraycopy()
方法相当复杂,*,JIT编译器不太可能将其内联(如其他答案之一所示)另一方面,JIT编译器很可能使用优化的调用序列,因为这是一种固有的本机方法。换句话说,这很可能不是正常的JNI调用
*-
System.arraycopy
不是一个简单的内存拷贝。它必须测试其参数,以避免读取或写入超出数组边界的内容,等等。在从一个对象数组复制到另一个对象数组的情况下,可能需要检查复制的每个对象的实际类型。所有这些加起来的代码远远超出了内联的合理范围