java可以使用JVM内联本机方法吗?
我写了一个小的静态JNI函数,只有5条指令长。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();
}
}
}
JVM是否可以将func
的代码内联到doLoop
中,或者将其编译为call func
# 1 楼答案
不,JVM基本上不能
本机函数的实现是二进制黑盒;JVM只知道一个入口点地址
本机代码不由虚拟机管理,不能在Java方法的上下文中执行。JVM将处于“in_java”状态的线程与处于“in_native”状态的线程区分开来。例如,本机线程不会在JVM安全点停止,这仅仅是因为JVM无法做到这一点
此外,本机方法调用并不是那么简单的操作A special procedure需要处理JNI调用的所有方面
# 2 楼答案
要让JVM完全安全地完成这项任务将非常困难,而且会有大量死角,所以几乎可以肯定不会
例如考虑以
结尾的C函数一个好的编译器会进行尾部调用优化,这样函数就可以编译成
而不是
因此,JVM在确定是否/如何内联一段本机代码时,需要做的不仅仅是寻找
ret
指令为了正确地内联本机方法,JVM作者必须考虑每一种可能的情况。他们很可能就是不想尝试
除了复杂的跳转,本机代码中的segfault还会出现在内联目标中,而不是单独的堆栈帧中
最好的建议是:制作一个包含所需循环的本机函数版本,或者如果它真的是5行简单的代码(不是库函数,或者其他扩展到很多asm的东西),只需用Java编写,让JIT编译器来担心它
# 3 楼答案
从字面上看,本机方法不能内联
然而,JVM可以用内部函数替换Java方法和本机方法。e、 g.许多不安全的方法都被视为内在的,不需要为JNI支付任何费用
因此,内部化的本机方法可以有效地内联