繁体   English   中英

Java内部方法和本机方法有什么区别?

[英]What is the difference between Java intrinsic and native methods?

Java 内部函数在很多地方都提到过(例如这里)。 我的理解是,这些是使用特殊本机代码处理的方法。 这似乎类似于 JNI 方法,它也是一个本机代码块。

有什么区别?

JIT 知道内在函数,因此它可以将相关的机器指令内联到它的 JIT 代码中,并作为热循环的一部分围绕它进行优化。

JNI 函数对于编译器来说是一个 100% 的黑盒,具有显着的调用/返回开销(特别是如果您仅将它用于标量)。

但即使它只是对int bitcount(unsigned x){ return __builtin_popcount(x); }类的函数的调用。 int bitcount(unsigned x){ return __builtin_popcount(x); }编译成 x86-64 popcnt eax, edi ; ret (x86-64 System V 调用约定)调用者(JIT 编译器正在发出)仍然必须假设所有调用破坏的寄存器都被破坏了。 在 x86-64 上,这是大多数整数寄存器和所有 FP/向量寄存器。 (就像提前 C++ 编译器调用黑盒函数与内在函数的成本一样)。 但我怀疑调用 JNI 函数的成本包括一些额外的开销。

当然,对任何未知函数的调用意味着如果 JIT 编译器无法证明没有其他任何东西对它们有引用,则可能需要将寄存器中的变量同步到内存中。 (逃脱分析。)

此外,内在函数意味着 JVM了解函数的作用,并可以通过它进行优化。 例如,通过不断传播,它知道 popcount(5) = 2 个设置位。 但是对于一个实际的 JNI 函数,它仍然必须调用它。 除非有某种方法将函数声明为“纯”,否则每次调用都是可见的副作用,因此它可以CSE

对于重度内联,编译时常量并不罕见。

主要区别在于 JVM知道内部方法的实现,并且可以用机器相关的优化指令(有时甚至是单处理器指令)替换原始 java 代码,而 JNI 方法的实现是未知的一个JVM。

后者施加了一些限制,例如无法为 JNI 方法应用某些优化技术,需要在调用堆栈上做额外的工作等。

PS您提供的链接包含该特定JVM的已知方法列表。 此列表可能因一个 JVM 而异。

“本机”方法是一个广义术语,表示该方法在 JVM 本身或动态加载的本机库中实现。

native方法是在类的 Java 源代码中声明为本native的方法。

“内在”方法是 JVM 运行时(特别是 JIT 编译器)对其执行特殊优化的方法。 “内在”的意思之一是调用序列不是 JNI 调用。 但优化可能比这更广泛。

请注意, native和“固有”是正交的:

  • 一个方法可能既是native的,也可能是“内在的”; 例如arraycopy 既是native又是“内在”的方法(通常)不会被实现为 JNI 方法。
  • 一个方法可能是“内在的”而不是native 例如,某些 Java 版本中的一些String方法。 在这种情况下,Java 源代码及其字节码在该方法的 JIT 编译版本中被忽略。

这似乎类似于 JNI 方法,它也是一个本机代码块。

JNI 是一种用于实现非“内在”的native方法的 API。 因此,JNI 方法是用 C/C++ 实现的方法,其签名与 JNI 调用序列兼容。

问题是 JNI 方法调用序列比典型的 Java 到 Java 或 Java 到内部调用序列更重。 (这是由于 JNI 调用的通用性,以及需要检查和映射 Java 对应的 C/C++ 类型之间的参数/结果......等等。)

与 Java 和内部方法相比,JNI 方法的另一个问题是 JIT 编译器对 JNI 方法实际在做什么的了解为零,因此无法调用边界应用各种优化; 例如内联。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM