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);
}
Критические нативы поддерживаются только в HotSpot JVM, начиная с JDK 7. Более того, «критическая» версия вызывается только из скомпилированного кода. Поэтому вам нужна как критическая, так и стандартная реализация, чтобы это работало правильно.
Эта функция была разработана для внутреннего использования в JDK. Там нет публичной спецификации или что-то в этом роде. Вероятно, единственная документация, которую вы можете найти, находится в комментариях к JDK-7013347.
Ориентир
Этот тест показывает, что критически важные нативные методы могут быть в несколько раз быстрее, чем обычные методы JNI, когда нативная рабочая нагрузка очень мала. . Чем длиннее метод, тем меньше относительные накладные расходы.
P.S. В 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
person
apangin
schedule
30.03.2016