Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java内在方法和本机方法之间的区别是什么?_Java_Native_Intrinsics - Fatal编程技术网

Java内在方法和本机方法之间的区别是什么?

Java内在方法和本机方法之间的区别是什么?,java,native,intrinsics,Java,Native,Intrinsics,Java内在函数在不同的地方被提到(例如)。我的理解是,这些方法使用特殊的本机代码进行处理。这似乎类似于JNI方法,它也是一个本机代码块 区别是什么?主要区别在于JVM知道内部方法的实现,可以用依赖机器的优化指令(有时甚至是单处理器指令)替换原始java代码,而JNI方法的实现对于JVM来说是未知的 后者施加了一些限制,例如不可能对JNI方法应用某些优化技术,需要对调用堆栈做额外的工作,等等 另外,您提供的链接包含指向特定JVM的已知方法的列表。此列表可能因JVM而异。JIT了解内部函数,因此它

Java内在函数在不同的地方被提到(例如)。我的理解是,这些方法使用特殊的本机代码进行处理。这似乎类似于JNI方法,它也是一个本机代码块


区别是什么?

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

后者施加了一些限制,例如不可能对JNI方法应用某些优化技术,需要对调用堆栈做额外的工作,等等


另外,您提供的链接包含指向特定JVM的已知方法的列表。此列表可能因JVM而异。

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

JNI函数对于编译器来说是一个100%的黑盒,具有很大的调用/返回开销(特别是当您仅将其用于标量时)

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

当然,对任何未知函数的调用意味着,如果JIT编译器不能证明其他任何函数都没有引用,那么寄存器中的变量可能需要同步到内存。(逃逸分析)

另外,内部函数意味着JVM理解函数的功能,并可以通过它进行优化。e、 g.通过恒定传播,它知道popcount(5)=2个设置位。但对于实际的JNI函数,它仍然需要调用它。每个调用都会产生明显的副作用,除非有某种方法可以将函数声明为“纯”函数

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

本机方法是一个广义术语,意味着该方法可以在JVM本身或动态加载的本机库中实现

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

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

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

  • 方法既可以是
    本机的
    方法,也可以是“固有的”;例如
    arraycopy
    。同时是
    本机
    和“内在”的方法(通常)不会作为JNI方法实现
  • 方法可以是“固有的”,而不是
    本机的
    ;例如,某些Java版本中的一些
    String
    方法。在本例中,在方法的JIT编译版本中,Java源代码及其字节码被忽略

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

JNI是一个API,用于实现非“内在”的
本机
方法。因此JNI方法是一种在C/C++中实现的与JNI调用序列兼容的签名。
问题在于JNI方法调用序列比典型的Java到Java或Java到内部调用序列更重。(这是由于JNI调用的通用性,以及需要在Java对应的C/C++类型之间检查和映射参数/结果……等等。)


与Java和内在方法相比,JNI方法的另一个问题是JIT编译器不知道前者在做什么,因此无法跨调用边界应用各种优化;e、 内联。

我认为区别在于,对于JNI调用,Java类知道它正在调用本机方法。有了intrinsic,JVM就决定用自己的实现透明地交换方法(在类的字节码中存在)。如果您使用的另一个JVM没有此内在特性,则会得到“正常”实现。内在方法是与JRE API中的方法完全对应的本机方法。CSE是什么意思?@Danilopiazzalanga: