Java JVM是否可以内联本机方法?

Java JVM是否可以内联本机方法?,java,x86,jvm,jit,Java,X86,Jvm,Jit,我编写了一个只有5条指令长的小型静态JNI函数。JVM是否可以将此代码内联到频繁调用它的方法体中,或者它是否总是在JITed方法中生成call指令 例如: public class SomeClass { private static native long func(); public void doLoop() { for(int i = 0; i < 0xFFFFFF; i++) { func(); }

我编写了一个只有5条指令长的小型静态JNI函数。JVM是否可以将此代码内联到频繁调用它的方法体中,或者它是否总是在JITed方法中生成
call
指令

例如:

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();
        }
    }
}
公共类SomeClass{
私有静态本机long func();
公共void doLoop(){
对于(int i=0;i<0xFFFFFF;i++){
func();
}
}  
公共静态void main(字符串[]args){
对于(int i=0;i<0xFFFFFF;i++){
doLoop();
}
}
}

JVM是否有可能将
func
的代码内联到
doLoop
中,或者将其编译为
call func
,JVM要完全安全地完成这项工作将是非常困难的,而且会遇到很多麻烦,所以几乎可以肯定不会

例如考虑以

结尾的C函数
return memcpy(dest, src, count);
一个好的编译器会进行尾部调用优化,这样函数就会编译成类似

mov   rdi, dest
mov   rsi, src
mov   edx, count
jmp   memcpy
而不是

...
call memcpy
ret
因此,JVM在确定是否/如何内联一段本机机器代码时,需要做的不仅仅是寻找
ret
指令

要正确内联本机方法,JVM作者必须考虑每一种可能的情况。他们很可能就是不想尝试

除了复杂的跳转,本机代码中的segfault将显示在内联目标中,而不是单独的堆栈帧中



最好的建议是:制作一个包含所需循环的本机函数版本,或者如果它实际上是5行简单的代码(不是库函数,或者其他扩展到很多asm的东西),只需用Java编写,让JIT编译器来担心它。

不,JVM基本上不能

本机函数的实现是二进制黑盒;JVM只知道入口点地址

本机代码不由虚拟机管理,不能在Java方法的上下文中执行。JVM区分处于“in_java”状态的线程和处于“in_native”状态的线程。例如,本机线程不会在JVM安全点停止,这仅仅是因为JVM无法做到这一点


此外,本机方法调用并不是那么简单的操作。需要解决JNI调用的所有方面。

从字面上看,本机方法不能内联

但是,JVM可以用内部函数替换Java方法和本机方法。e、 g.许多不安全的方法被视为内在的,并且不为JNI支付预扣税


因此,内部化的本机方法可以有效地进行内联。

如果只有5条指令,听起来您实际上需要内联汇编。我认为jnr可以为x86做到这一点,但文档很少,这可能只是实验性的东西。