Что делает вызовы JNI медленными? - PullRequest
182 голосов
/ 08 октября 2011

Я знаю, что «пересечение границ» при выполнении вызова JNI в Java является медленным.

Однако я хочу знать Что что делает его медленным?Что делает базовая реализация jvm при выполнении вызова JNI, который делает его таким медленным?

Ответы [ 3 ]

165 голосов
/ 18 октября 2011

Во-первых, стоит отметить, что под «медленным» мы говорим о чем-то, что может занять десятки наносекунд. Для простых тривиальных методов в 2010 году я измерил вызовы в среднем на 40 нс на моем рабочем столе Windows и 11 нс на моем рабочем столе Mac. Если вы не делаете много звонков, вы не будете замечать.

Тем не менее, вызов нативного метода может быть медленнее , чем обычный вызов метода Java. Причины включают в себя:

  • Собственные методы не будут встроены JVM. И при этом они не будут точно скомпилированы для этой конкретной машины - они уже скомпилированы.
  • Массив Java может быть скопирован для доступа в нативный код, а затем скопирован обратно. Стоимость может быть линейной по размеру массива. Я измерил JNI , копирующий массива 100 000, в среднем около 75 микросекунд на моем рабочем столе Windows и 82 микросекунд на Mac. К счастью, прямой доступ может быть получен через GetPrimitiveArrayCritical или NewDirectByteBuffer .
  • Если методу передан объект или ему необходимо выполнить обратный вызов, то нативный метод, скорее всего, будет делать свои собственные вызовы JVM. Доступ к полям, методам и типам Java из нативного кода требует чего-то похожего на рефлексию. Подписи указываются в строках и запрашиваются в JVM. Это медленный и подвержен ошибкам.
  • Строки Java являются объектами, имеют длину и кодируются. Для доступа к строке или ее создания может потребоваться копия O (n).

Некоторое дополнительное обсуждение, возможно, датированное, можно найти в статье «Производительность платформы Java: стратегии и тактики», 2000 г., Стив Уилсон и Джефф Кессельман, в разделе «9.2: Изучение затрат JNI». Это примерно треть пути вниз этой страницы , предоставленной в комментарии @Philip ниже.

Документ IBM developerWorks 2009 года "Лучшие практики использования собственного интерфейса Java" содержит некоторые предложения по предотвращению ошибок производительности с JNI.

23 голосов
/ 15 июля 2012

Стоит отметить, что не все методы Java, отмеченные native, являются «медленными». Некоторые из них встроенные , что делает их чрезвычайно быстрыми. Чтобы проверить, какие из них являются внутренними, а какие нет, вы можете поискать do_intrinsic в vmSymbols.hpp .

22 голосов
/ 08 октября 2011

По сути, JVM интерпретирует параметры C для каждого вызова JNI, и код не оптимизируется.

В есть еще много подробностей

ЕслиВы заинтересованы в бенчмаркинге JNI по сравнению с собственным кодом , в этом проекте есть код для запуска тестов.

...