Java intrinsic functions are mentioned in various places (e.g. here). My understanding is that these are methods that handled with special native code. This seems similar to a JNI method which is also a block of native code.
What is the difference?
A Java method is generically a code block with a name that you can write using plain java. A native method is a method that is linked to a native library.
Native methods are Java™ methods that start in a language other than Java. Native methods can access system-specific functions and APIs that are not available directly in Java. The use of native methods limits the portability of an application, because it involves system-specific code.
Native Method Stacks. An implementation of the Java Virtual Machine may use conventional stacks, colloquially called "C stacks," to support native methods (methods written in a language other than the Java programming language).
The native modifier indicates that a method is implemented in platform-dependent code, often seen in C language. Native modifier indicates that a method is implemented in platform-dependent code, often in C.
The JIT knows about intrinsics, so it can inline the relevant machine instruction into the code it's JITing, and optimize around it as part of a hot loop.
A JNI function is a 100% black box for the compiler, with significant call/return overhead (especially if you use it for just a scalar).
But even if it were just a call to a function like int bitcount(unsigned x){ return __builtin_popcount(x); }
that compiled to x86-64 popcnt eax, edi
; ret
(x86-64 System V calling convention) the caller (which the JIT compiler is emitting) would still have to assume that all the call-clobbered registers were clobbered. On x86-64, that's most of the integer registers and all the FP/vector registers. (Just like the cost for an ahead-of-time C++ compiler for calling a black-box function vs. an intrinsic). But I suspect the cost for calling a JNI function includes some extra overhead on top of that.
And of course a call to any unknown function means that variables which were in registers might need to be synced to memory if the JIT compiler can't prove that nothing else has a reference to them. (Escape analysis.)
Plus, intrinsics mean the JVM understands what the function does, and can optimize through it. e.g. with constant propagation, it knows that popcount(5) = 2 set bits. But with an actual JNI function, it would still have to call it. And every call is a visible side-effect unless there's some way to declare the function as "pure" so it can CSE.
With heavy inlining, compile time constants are not rare.
The main difference is that a JVM knows the implementation of an intrinsic method and can substitute the original java-code with machine-dependent well-optimized instructions (sometimes even with a single processor instruction), whereas the implementation of a JNI method is unknown to a JVM.
The latter impose some restrictions such as impossibility to apply certain optimization techniques for JNI methods, the need to do an extra work on the call stack, etc.
P.S. The link you have provided contains a list of known methods to that specific JVM. This list may differ from one JVM to another.
A "native" method is a broad term meaning that the method is implemented either in the JVM itself or a dynamically loaded native library.
A native
method is a method that is declared as native
in the Java source code of the class.
An "intrinsic" method is one that the JVM runtime (specifically the JIT compiler) performs special optimization on. One of the things that "intrinsic" means is that the call sequence is not a JNI call. But the optimizations may be more extensive than that.
Note that native
and "intrisic" are orthogonal:
native
and "intrinsic"; for example arraycopy
. A method that is both native
and "intrinsic" will (typically) not be implemented as a JNI method.native
; for example some String
methods in some versions of Java. In this case, the Java source code and its bytcodes are ignored in the JIT compiled version of the method.This seems similar to a JNI method which is also a block of native code.
JNI is an API for implementing native
methods that are not "intrinsic". So a JNI method is a method implemented in C / C++ with a signature that is compatible with a JNI calling sequence.
The problem is that the JNI method call sequence is more heavy weight than a typical Java-to-Java or Java-to-intrinsic calling sequence. (This is due to the generic nature of a JNI call, and the need to check and map arguments / results between Java corresponding C/C++ types ... and things like that.)
The other problem with JNI methods compared with Java and intrinsic methods is that the JIT compiler has zero knowledge of what JNI methods are actually doing, and is therefore unable to apply various optimizations across the call boundary; e.g. inlining.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With