简体   繁体   中英

Can the JVM inline native methods?

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

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.

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.

eg 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.

Taken literally, native methods cannot be inlined.

However, the JVM can replace both Java methods and native methods with intrinsics. eg 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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