Reputation: 1132
I wrote a small static JNI function which is only 5 instructions long. Is it possible for the JVM to inline this code into the body of a method which calls it frequently or will it always generate a call
instruction in the JITed method?
For example:
public class SomeClass {
private static native long func();
public void doLoop() {
for(int i = 0; i < 0xFFFFFF; i++) {
func();
}
}
public static void main(String[] args) {
for(int i = 0; i < 0xFFFFFF; i++) {
doLoop();
}
}
}
Is it possible for the JVM to inline the code of func
into doLoop
or will it just compile it as call func
Upvotes: 2
Views: 1217
Reputation: 98284
No, JVM basically can't.
The implementation of a native function is a binary blackbox; the only thing JVM knows about it is an entry point address.
The native code is not managed by the Virtual Machine and cannot be executed in the context of Java method. JVM distinguishes between threads being 'in_java' state from threads being 'in_native'. For example, native threads are not stopped at JVM safepoint, simply because there is no way for JVM to do this.
Furthermore, a native method call is not so simple operation. A special procedure is required to address all aspects of a JNI call.
Upvotes: 11
Reputation: 533472
Taken literally, native methods cannot be inlined.
However, the JVM can replace both Java methods and native methods with intrinsics. e.g. many of the Unsafe methods are treated as intrinsics and don't pay a prenalty for JNI.
As such, native methods which are intrinsicified can be effectively inlined.
Upvotes: 0
Reputation: 364039
It would be very hard and have a ton of corner cases for the JVM to do it with full safety, so almost certainly no.
e.g. consider a C function that ends with
return memcpy(dest, src, count);
A decent compiler will do tail-call optimization so the function will compile to something like
mov rdi, dest
mov rsi, src
mov edx, count
jmp memcpy
Rather than
...
call memcpy
ret
So the JVM has to do more than look for ret
instructions when figuring out if / how it could inline a piece of native machine code.
To correctly inline a native method, the JVM authors would have to think of every possible corner case. It's highly likely they just wouldn't try.
Besides tricky jumps, a segfault in the native code would show up in inline target, rather than in a separate stack frame.
Best suggestion: make a version of your native function that contains the loop you need, or if it's really 5 simple lines (not library functions, or other stuff that expands to a lot of asm), just write it in Java and let the JIT-compiler worry about it.
Upvotes: 4