Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

В разработке программного обеспечения , то Java Native Interface ( JNI ) представляет собой интерфейс внешней функции программирования основы , которая позволяет Java - код работает в виртуальной машине Java (JVM) для вызова и вызываться [1] нативные приложения (программы , специфичные для аппаратного обеспечения и операционной системная платформа) и библиотеки, написанные на других языках, таких как C , C ++ и ассемблер .

Цели [ править ]

JNI позволяет программистам писать собственные методы для обработки ситуаций, когда приложение не может быть полностью написано на языке программирования Java, например, когда стандартная библиотека классов Java не поддерживает специфичные для платформы функции или программную библиотеку. Он также используется для изменения существующего приложения (написанного на другом языке программирования), чтобы оно стало доступным для приложений Java. Многие из стандартных библиотечных классов зависят от JNI для обеспечения функциональности для разработчика и пользователя, например, файлового ввода-вывода и звуковых возможностей. Включение реализаций API, зависящих от производительности и платформы, в стандартную библиотеку позволяет всем приложениям Java получать доступ к этой функции безопасным и независимым от платформы способом.

Инфраструктура JNI позволяет собственному методу использовать объекты Java так же, как код Java использует эти объекты. Собственный метод может создавать объекты Java, а затем проверять и использовать эти объекты для выполнения своих задач. Собственный метод также может проверять и использовать объекты, созданные кодом Java-приложения.

Только приложения и подписанные апплеты могут вызывать JNI.

Приложение, которое полагается на JNI, теряет возможности переносимости платформы, предлагаемые Java (частичный обходной путь состоит в том, чтобы написать отдельную реализацию кода JNI для каждой платформы и заставить Java определять операционную систему и загружать правильную во время выполнения).

Не только собственный код может взаимодействовать с Java, он также может использовать Java Canvas, что возможно с помощью Java AWT Native Interface . Процесс почти такой же, с небольшими изменениями. Собственный интерфейс Java AWT доступен только с J2SE 1.3.

JNI также обеспечивает прямой доступ к ассемблерному коду , даже не используя мост C. [2] Таким же образом возможен доступ к Java-приложениям из сборки. [3]

Дизайн [ править ]

В структуре JNI собственные функции реализованы в отдельных файлах .c или .cpp. (C ++ предоставляет несколько более простой интерфейс с JNI.) Когда JVM вызывает функцию, она передает JNIEnvуказатель, jobjectуказатель и любые аргументы Java, объявленные методом Java. Например, следующее преобразует строку Java в собственную строку:

ехЬегп  "С" JNIEXPORT  недействительными  JNICALL  Java_ClassName_MethodName  ( JNIEnv  * ENV ,  jobject  OBJ ,  jstring  javaString ) {  Const  символ  * nativeString  =  ENV -> GetStringUTFChars ( javaString ,  0 ); // Делаем что-нибудь с nativeString env -> ReleaseStringUTFChars ( javaString ,  nativeString ); }

envУказатель представляет собой структуру , которая содержит интерфейс для виртуальной машины Java. Он включает в себя все функции, необходимые для взаимодействия с JVM и работы с объектами Java. Примеры функций JNI - это преобразование собственных массивов в / из массивов Java, преобразование собственных строк в / из строк Java, создание экземпляров объектов, выдача исключений и т. Д. По сути, все, что может делать код Java, можно сделать с помощью JNIEnv, хотя и со значительно меньшей легкостью.

Аргумент obj- это ссылка на объект Java, внутри которого был объявлен этот собственный метод.

Собственные типы данных могут быть отображены в / из типов данных Java. Для составных типов, таких как объекты, массивы и строки, собственный код должен явно преобразовывать данные, вызывая методы в JNIEnv.

Указатель среды JNI ( JNIEnv * ) передается в качестве аргумента для каждой встроенной функции, сопоставленной с методом Java, что позволяет взаимодействовать со средой JNI внутри встроенного метода. Этот указатель интерфейса JNI может быть сохранен, но остается действительным только в текущем потоке. Другие потоки должны сначала вызвать AttachCurrentThread (), чтобы присоединиться к виртуальной машине и получить указатель интерфейса JNI. После присоединения собственный поток работает как обычный поток Java, работающий в собственном методе. Собственный поток остается подключенным к виртуальной машине до тех пор, пока он не вызовет DetachCurrentThread () для отключения. [4]

Платформа JNI не обеспечивает автоматической сборки мусора для ресурсов памяти, не относящихся к JVM, выделенных кодом, выполняющимся на собственной стороне. Следовательно, собственный сторонний код (например, язык ассемблера) берет на себя ответственность за явное освобождение любых таких ресурсов памяти, которые получает собственный код.

На платформах Linux и Solaris, если собственный код регистрируется как обработчик сигналов, он может перехватывать сигналы, предназначенные для JVM. Можно использовать цепочку ответственности , чтобы машинный код мог лучше взаимодействовать с JVM. На платформах Windows структурированная обработка исключений (SEH) может использоваться для обертывания собственного кода в блоках попытки / отлова SEH, чтобы захватывать программные прерывания, сгенерированные машиной (CPU / FPU) (например, нарушения доступа с нулевым указателем и операции деления на ноль. ) и обрабатывать эти ситуации до того, как прерывание будет передано обратно в JVM (то есть в сторонний код Java), что, по всей вероятности, приведет к необработанному исключению. [ оригинальное исследование? ]

Кодировка, используемая для функций NewStringUTF, GetStringUTFLength, GetStringUTFChars, ReleaseStringUTFChars и GetStringUTFRegion, - это «модифицированный UTF-8» [5], который не является допустимым UTF-8 для всех входных данных, но на самом деле это другая кодировка. Нулевой символ (U + 0000) и кодовые точки не на базовой многоязычной плоскости (больше или равны U + 10000, то есть те, которые представлены в виде суррогатных парв UTF-16) по-разному кодируются в модифицированном UTF-8. Многие программы на самом деле используют эти функции неправильно и обрабатывают строки UTF-8, возвращаемые или передаваемые в функции, как стандартные строки UTF-8, а не модифицированные строки UTF-8. Программы должны использовать функции NewString, GetStringLength, GetStringChars, ReleaseStringChars, GetStringRegion, GetStringCritical и ReleaseStringCritical, которые используют кодировку UTF-16LE в архитектурах с прямым порядком байтов и UTF-16BE в архитектурах с прямым порядком байтов, а затем использовать UTF-16 для UTF-16. 8 процедура преобразования. [ оригинальное исследование? ]

Типы карт [ править ]

В следующей таблице показано сопоставление типов между Java (JNI) и собственным кодом.

Кроме того, подпись "L fully-qualified-class ;"будет означать класс, однозначно указанный этим именем; например, подпись "Ljava/lang/String;"относится к классу java.lang.String. Кроме того, префикс [подписи делает массив этого типа; например, [Iозначает тип массива int. Наконец, voidподпись использует Vкод.

Эти типы взаимозаменяемы. Можно использовать jintтам, где вы обычно используете int, и наоборот, без необходимости приведения типов . Однако сопоставление строк и массивов Java с собственными строками и массивами отличается. Если вместо a jstringиспользуется a char *, код может привести к сбою JVM. [ оригинальное исследование? ]

Производительность [ править ]

JNI влечет за собой значительные накладные расходы и снижение производительности при определенных обстоятельствах: [6]

  • Вызов функций к методам JNI обходится дорого, особенно при повторном вызове метода.
  • Собственные методы не встроены JVM, и метод не может быть скомпилирован JIT , поскольку метод уже скомпилирован.
  • Массив Java может быть скопирован для доступа в машинном коде, а затем скопирован обратно. Стоимость может быть линейной в зависимости от размера массива.
  • Если методу передается объект или ему необходимо выполнить обратный вызов, то собственный метод, скорее всего, будет делать свои собственные вызовы JVM. Доступ к полям, методам и типам Java из нативного кода требует чего-то похожего на отражение . Подписи указываются в строках и запрашиваются из JVM. Это и медленно, и подвержено ошибкам.
  • Строки Java являются объектами, имеют длину и закодированы. Для доступа к строке или ее создания может потребоваться O (n) копия.

Альтернативы [ править ]

Собственная реализация Microsoft виртуальной машины Java ( Visual J ++ ) имела аналогичный механизм для вызова собственного кода из Java, называемый Raw Native Interface ( RNI ). Кроме того, у него был простой способ вызвать существующий собственный код, который сам не знал о Java, такой как (но не ограничиваясь) Windows API, называемый J / Direct . Однако после судебного разбирательства между Sun и Microsoft по поводу этой реализации Visual J ++ больше не поддерживается.

RNI было менее неуклюжим в использовании, чем JNI, потому что не требовалось учета с указателем среды Java. Вместо этого можно было получить прямой доступ ко всем объектам Java. Чтобы облегчить это, использовался инструмент, который генерировал файлы заголовков из классов Java. Точно так же J / Direct было проще использовать, чем использовать необходимую промежуточную родную библиотеку и JNI, хотя в настоящее время JNA является альтернативой. [ оригинальное исследование? ]

См. Также [ править ]

  • GIWS (программное обеспечение)
  • Gluegen
  • Сервисы вызова платформы
  • SWIG

Ссылки [ править ]

  1. ^ «Обзор собственного интерфейса Java» . Руководство и спецификация Java Native Interface Programmer . Проверено 27 декабря 2018 .
  2. ^ «Вызов программ на языке ассемблера из Java» . Java.net. 2006-10-19. Архивировано из оригинала на 2008-03-30 . Проверено 6 октября 2007 .
  3. ^ «Запуск приложений Java из программ на языке ассемблера» . Java.net. 2006-10-19. Архивировано из оригинала на 2007-10-11 . Проверено 4 октября 2007 .
  4. ^ API вызова. Sun Microsystems. https://docs.oracle.com/en/java/javase/11/docs/specs/jni/invocation.html
  5. ^ «Типы JNI и структуры данных» .
  6. ^ «java - Что замедляет вызовы JNI? - Переполнение стека» .

Библиография [ править ]

 refbegin цитировать книгу first = Роб last = Гордон date = март 1998 г. title = Essential Jni: собственный интерфейс Java издатель = Prentice Hall edition = 1st страниц = 498 isbn = 0-13-679895-0 url = http://www.informit.com/store/product.aspx?isbn=9780136798958 цитировать книгу first = Шэн last = Лян date = 20 июня 1999 г. title = Собственный интерфейс Java (TM): Руководство программиста и спецификация издатель = Prentice Hall edition = 1st страниц = 320 isbn = 0-201-32577-2 url = http://www.informit.com/store/product.aspx?isbn=9780201325775
 Возврат очаровательны.

Внешние ссылки [ править ]

  • Спецификация Oracle JNI 6.0 API
  • Собственный интерфейс Java: Руководство и спецификация программиста
  • JNI в XCode от Apple
  • Обработка исключений в JNI
  • JavaLink (современная оболочка C ++ 17 для JNI)