Ответ 1
Вызов метода JNI из Java довольно дорого по сравнению с простым вызовом функции C. HotSpot обычно выполняет большинство из следующих шагов для вызова метода JNI:
- Создайте фрейм стека.
- Переместить аргументы в соответствующие регистры или местоположения стека в соответствии с ABI.
- Оберните ссылки на объекты для дескрипторов JNI.
- Получите
JNIEnv*
иjclass
для статических методов и передайте их в качестве дополнительных аргументов. - Проверьте, следует ли вызывать функцию трассировки
method_entry
. - Заблокировать монитор объекта, если метод
synchronized
. - Проверьте, не связана ли родная функция. Поиск функции и привязка выполняются лениво.
- Отключить поток от
in_java
доin_native
. - Вызов функции native
- Проверьте, требуется ли safepoint.
- Возвращает поток в состояние
in_java
. - Отключить монитор, если он заблокирован.
- Сообщить
method_exit
. - Результат объекта unwrap и reset JNI обрабатывает блок.
- Обработать исключения JNI.
- Удалите фрейм стека.
Исходный код этой процедуры можно найти в SharedRuntime:: generate_native_wrapper.
Как вы можете видеть, накладные расходы могут быть значительными. Но во многих случаях большинство вышеуказанных шагов не являются необходимыми. Например, если собственный метод просто выполняет некоторую кодировку/декодирование в байтовом массиве и не генерирует никаких исключений и не вызывает другие функции JNI. Для этих случаев HotSpot имеет нестандартное (и неизвестное) соглашение под названием Critical Natives
, обсуждаемое здесь.