【问题标题】:What is the difference between Java intrinsic and native methods?Java内部方法和本机方法有什么区别?
【发布时间】:2019-11-04 00:43:21
【问题描述】:

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

有什么区别?

【问题讨论】:

  • 我认为不同之处在于,对于 JNI 调用,您的 Java 类知道它正在调用本机方法。使用内在函数,JVM 只是决定用自己的实现透明地交换方法(存在于类中的字节码中)。如果您使用没有此内在函数的不同 JVM,您将获得“正常”实现。
  • 内在方法是与 JRE API 中的方法完全对应的本地方法。

标签: java native intrinsics


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

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

    但即使它只是对像 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

    使用大量内联,编译时常量并不罕见。

    【讨论】:

    【解决方案3】:

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

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

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

    注意native 和“intrisic”是正交的:

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2013-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-06
      • 1970-01-01
      相关资源
      最近更新 更多