Собственный интерфейс Java

редактировать

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

Содержание
  • 1 Цели
  • 2 Дизайн
  • 3 Типы сопоставления
  • 4 Производительность
  • 5 Альтернативы
  • 6 См. Также
  • 7 Ссылки
  • 8 Библиография
  • 9 Внешние ссылки
Цели

JNI позволяет программистам писать собственные методы для обработки ситуаций, когда приложение не может быть полностью написано на языке программирования Java, например когда стандартная библиотека Java class не поддерживает специфичные для платформы функции или программную библиотеку. Он также используется для изменения существующего приложения (написанного на другом языке программирования), чтобы оно стало доступным для приложений 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. Таким же образом возможен доступ к приложениям Java из сборки.

Дизайн

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

extern "C" JNIEXPORT void JNICALL Имя_класса_в_классе_MethodName (JNIEnv * env, jobject obj, jstring javaString) {const char * nativeString = env->GetStringUTFChars (javaStringUTFChars (javaStringUTFChars)); // Сделаем что-нибудь с nativeString env->ReleaseStringUTFChars (javaString, nativeString); }

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

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

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

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

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

На платформах Linux и Solaris, если собственный код регистрирует себя как обработчик сигналов, он может перехватывать сигналы, предназначенные для JVM. Цепочка ответственности может использоваться, чтобы позволить машинному коду лучше взаимодействовать с JVM. На платформах Windows Structured Exception Handling (SEH) может использоваться для обертывания собственного кода в блоках SEH try / catch, чтобы фиксировать программные прерывания, сгенерированные машиной (CPU / FPU) (например, нарушения доступа NULL-указателя и деления на ноль), и для обработки этих ситуаций до того, как прерывание будет передано обратно в JVM (т.е. побочный код Java), что, по всей вероятности, приведет к необработанному исключению.

Кодировка, используемая для Функции NewStringUTF, GetStringUTFLength, GetStringUTFChars, ReleaseStringUTFChars и GetStringUTFRegion - это «модифицированный UTF-8», который не является допустимым 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) и машинным кодом.

Тип CТип языка JavaОписаниеСигнатура типа
unsigned charjboolean8 бит без знакаZ
подписанный charjbyteподписанный 8 битB
беззнаковый короткийjcharбеззнаковый 16 битC
короткийjshort16 бит со знакомS
longjint32 бита со знакомI

long long. __int64

jlong ​​64 бита со знакомJ
floatjfloat32 битаF
doublejdouble64 битаD
voidV

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

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

Performance

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

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

Собственная реализация виртуальной машины Java от Microsoft (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.

См. Также
Ссылки
Библиография
Внешние ссылки
Последняя правка сделана 2021-05-24 03:57:19
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте