JNI有那么慢吗?
JNI已经进行了大量优化,您应该先尝试一下。但它确实有一定的开销,请参阅详细信息。
如果本机函数很简单并且经常被调用,则此开销可能很大。JDK 有一个名为 Critical Natives 的私有 API,以减少调用不需要太多 JNI 功能的函数的开销。
关键原住民
本机方法必须满足以下条件才能成为关键本机方法:
- 必须是静态的,不同步;
- 参数类型必须是基元数组或基元数组;
- 实现不得调用 JNI 函数,即它不能分配 Java 对象或引发异常;
- 不应该长时间运行,因为它会在运行时阻塞GC。
关键本机的声明看起来像常规的 JNI 方法,除了
- 它以而不是
JavaCritical_
Java_
;
- 它没有额外的和参数;
JNIEnv*
jclass
- Java 数组在两个参数中传递:第一个是数组长度,第二个是指向原始数组数据的指针。也就是说,无需打电话和朋友,就可以立即使用直接数组指针。
GetArrayElements
例如,JNI 方法
JNIEXPORT jint JNICALL
Java_com_package_MyClass_nativeMethod(JNIEnv* env, jclass klass, jbyteArray array) {
jboolean isCopy;
jint length = (*env)->GetArrayLength(env, array);
jbyte* buf = (*env)->GetByteArrayElements(env, array, &isCopy);
jint result = process(buf, length);
(*env)->ReleaseByteArrayElements(env, array, buf, JNI_ABORT);
return result;
}
将转到
JNIEXPORT jint JNICALL
JavaCritical_com_package_MyClass_nativeMethod(jint length, jbyte* buf) {
return process(buf, length);
}
关键原生仅在从 JDK 7 开始的 HotSpot JVM 中受支持。此外,“关键”版本仅从编译的代码中调用。因此,您需要关键和标准实现才能使其正常工作。
此功能是为在 JDK 中内部使用而设计的。没有公共规范或其他东西。您可能找到的唯一文档是在JDK-7013347的注释中。
基准
此基准测试表明,当本机工作负载非常小时,关键本机可能比常规 JNI 方法快几倍。方法越长,相对开销越小。
附言JDK 中正在进行一项实现 Native MethodHandles 的工作,这将作为 JNI 的更快替代方案。但是,它不太可能出现在JDK 10之前。
- http://cr.openjdk.java.net/~jrose/panama/native-call-primitive.html
- http://mail.openjdk.java.net/pipermail/panama-dev/2015-December/000225.html