Ответ 1
Является ли JNI медленным?
JNI уже оптимизирован, вы должны сначала попробовать. Но у этого действительно есть определенные накладные расходы, см. Подробности.
Эти служебные данные могут быть значительными, если нативная функция проста и часто называется. JDK имеет частный API под названием Critical Natives, чтобы уменьшить накладные расходы на функции вызова, которые не требуют значительной части возможностей 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);
}
Критические туземцы поддерживаются только в JSM HotSpot, начиная с JDK 7. Кроме того, "критическая" версия вызывается только из скомпилированного кода. Поэтому для обеспечения правильной работы вам нужна как критическая, так и стандартная реализация.
Эта функция была разработана для внутреннего использования в JDK. Нет никакой публичной спецификации или чего-то еще. Вероятно, единственная документация, которую вы можете найти, находится в комментариях к JDK-7013347.
Benchmark
Этот тест показывает, что критические уроженцы могут быть в несколько раз быстрее обычных JNI-методов, когда нагрузка на рабочую область очень мала. Чем дольше метод, тем меньше относительные служебные данные.
P.S. В JDK продолжается работа по реализации Native MethodHandles, которая будет служить более быстрой альтернативой JNI. Однако вряд ли он появится до JDK 10.