JNI - 10c15-30

advertisement
Java Native Interface
(JNI)
Что такое JNI ?

Java Native Interface (JNI) —
стандартный механизм Java, с помощью
которого Java-код может взаимодействовать с
системным или прикладным собственным
кодом (вызывать его и вызываться им),
написанным на языках подобных С, C++ или
ассемблера, скомпилированным и работающим
непосредственно под управлением той или
иной операционной системы.
Что такое JNI ?
Взаимодействие Java с другими
языками
Взаимодействие кодов JAVA и С/С++
может осуществляться двумя способами


С/С++ - код получает управление непосредственно из
JAVA-программы путем вызова собственного (NATIVE)
метода
С/С++ - код динамически загружает JVM с помощью
INVOCATION API
JNI – NATIVE метод

Необходимо создать собственный JAVA-метод

Сгенерировать с помощью утилиты JAVAH заголовочный
файл для С/С++ - функций

Разработать сами функции, в которые будет
передаваться управление

Оттранслировать функции поместив в библиотечный
файл

После создания библиотеки ее можно загружать из JAVAпрограммы для последующего вызова собственных
методов.
JNI – INVOCATION API метод




Использование INVOCATION API позволяет встраивать
JVM в приложения (без необходимости их статического
связывания с кодом самой JVM)
управление изначально находится в С/С++ - программе.
INVOCATION API состоит из небольшого набора функций,
позволяющих создавать и уничтожать JVM в текущем
процессе
присоединять и отсоединять текущий поток от JVM
Используя JNI,
собственные методы могут

Создавать, проверять и обновлять Java объекты
(включая массивы и типы String)

Вызывать Java методы

Ловить и выбрасывать исключения

Загружать классы и получать информацию о классах

Выполнять проверку типов во время исполнения
JNI определяет ~210
прикладных функций


Доступ к JNI-функциям из С/С++ -функции можно
получить через интерфейсный указатель JNIENV*
Указатель JNIENV* передается каждой С/С++ функции, представляющей реализацию собственного
метода
Все ~210 функции разделены
на ~14 групп














информация о версии JNI
операции с классами
исключения (EXCEPTIONS)
обработка глобальных и локальных ссылок
операции с объектами
доступ к данным объекта
вызов методов объекта (INSTANCE METHOD)
доступ к статическим данным объекта
вызов методов класса (CLASS METHOD)
операции со строковыми объектами
операции с массивами
регистрация собственных методов
операции с мониторами (MONITOR OPERATIONS)
интерфейс с JVM
JNI и исключения в Java

Throw( )
Выбрасывает существующий объект исключения.
Используется в собственном объекте для повторного
выбрасывания исключения.

ThrowNew( )

ExceptionOccurred( )

ExceptionDescribe( )


Создает новый объект исключения и выбрасывает его.
Определяет, было ли исключение уже выброшено, но
еще не очищено.
Печатает исключение и содержимое стека.
ExceptionClear( )
Очищает рассматриваемое исключение.
FatalError( )
Вызывает фатальную ошибку. Возврата нет.
Основные этапы реализации
native метода используя JNI
1.
Создание класса который объявляет native метод.
2.
Компиляция программы
3.
Используя javah –jni создать заголовочный файл
C/С++ (.h)
4.
Написание реализации выполнения native метода, (.с)
5.
Компиляция С кода в dll или so библиотеку
6.
Запуск Java приложения используя полученную
библиотеку
Создание собственного
JAVA-метода




Собственный метод создается путем добавления к его
описанию спецификатора NATIVE, при этом он не должен
иметь реализации (так же как и методы в описании
интерфейса).
Спецификатор NATIVE сообщает компилятору, что
реализация данного метода будет представлена в виде
откомпилированного С/С++ - кода, помещенного в
библиотечный файл.
Когда JVM встречает обращение к собственному методу,
происходит вызов соответствующей С/С++ - функции.
Помимо описания собственного метода, JAVA-код должен
динамически загрузить библиотеку, содержащую С/С++
- функцию с реализацией данного метода.
Создание класса который
объявляет native метод
class HelloWorld
{
//native метод
public native void displayHello();
//Статическая инициализация
static {
//динамически загрузить библиотеки
System.loadLibrary("c_library");
}
}
public static void main(String[] args) {
//создание нового объекта
HelloWorld hw = new HelloWorld();
// вызов метода реализованного в С/С++
hw.displayHello();
}
Метод LOADLIBRARY()




вызывается в статическом инициализаторе, что
обеспечивает единственный вызов этого метода после
загрузки класса.
можно вызывать более одного раза (например, в
конструкторе), загрузка библиотеки будет происходить
только при первом обращении к LOADLIBRARY(), при
последующих вызовах этого метода определяется, что
библиотека уже загружена и будет просто возвращаться
управление.
преобразует свой параметр в соответствии с тем, как
именуются библиотечные файлы на конкретной
платформе (dll, so)
использует стандартный алгоритм поиска библиотеки
для данной платформы
LOADLIBRARY() алгоритм поиска
библиотеки для WIN32 DLL
Для WIN32 DLL может находиться
• в текущем каталоге процесса
• в каталоге, содержащем EXE-файл (то есть
исполняемый модуль JVM, находящийся в
подкаталоге BIN основного каталога JAVA)
• в системном каталоге WIN32
• в каталоге WINDOWS
• в каталогах, указанных в переменной окружения
PATH
LOADLIBRARY() алгоритм поиска
библиотеки для UNIX
Для UNIX библиотечный файл может находиться
• в текущем каталоге процесса
• в подкаталоге LIB основного каталога JAVA
• в каталогах, перечисленных в переменной окружения
LD_LIBRARY_PATH
LOADLIBRARY() исключительная ситуация
JAVA.LANG.UNSATISFIEDLINKERROR

Если указанную библиотеку найти не удается

Если метод не найден
Компиляция программы


Ничем не отличается от компиляции обычных программ.
Например, если записать пример в файл с именем
APP.JAVA, то для его компиляции необходимо выполнить
следующую команду:
C:\ JAVAC APP.JAVA
Создание заголовочного файла
Его можно написать:
• В ручную
• Воспользоваться утилитой JAVAH
Утилита JAVAH



При обращении к утилите JAVAH указывается имя класса
и параметр -JNI
Утилита JAVAH анализирует CLASS-файл и строит
заголовочный файл
В качестве имен создаваемых заголовочных файлов
используются полные квалифицированные имена
классов, которые описаны в указанном файле и
содержат собственные методы
Создание заголовочного файла
используя JAVAH
JAVAH -JNI HelloWorld
 Выходной файл HelloWorld.h

Содержимое заголовочного
файла
#include <JNI.H> /* Header for class Example */
#ifndef _Included_Example
#define _Included_Example
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Example
* Method: nativeMethod
* Signature: ()V
*/
JNIEXPORT VOID JNICALL Java_displayHello_helloWorld (JNIEnv *,
jobject);
#ifdef __cplusplus
}
#endif
#endif
Содержимое заголовочного
файла



Директива препроцессора #INCLUDE <JNI.H> включает
файл JNI.H (из подкаталога INLCUDE основного каталога
JAVA), в котором находятся все необходимые объявления
типов и функций для реализации собственного метода.
Макросы JNIEXPORT и JNICALL необходимы только для
платформы WIN32, где они раскрываются
соответственно в __DECLSPEC(DLLEXPORT) и __STDCALL
и позволяют более эффективно строить DLL. Платформа
UNIX использует для этих целей обычные С-соглашения,
поэтому указанные макросы раскрываются в пустые
строки.
имя С/С++ - функции значительно отличается от имени
собственного JAVA-метода. При построении имени С/С++
- функции и использовании JNI-функций является
сигнатура метода (SIGNATURE или METHOD ARGUMENTS
SIGNATURE).
Сигнатура метода



Сигнатура метода - это сокращенная
форма записи параметров метода и
типов возвращаемого значения.
В сигнатуру не входят ни имя метода, ни
имена параметров.
JNI формирует сигнатуры в соответствии
с правилами
METHOD ARGUMENTS
SIGNATURE
Знак сигнатуры
JAVA-тип
Z
BOOLEAN
B
BYTE
C
CHAR
S
SHORT
I
INT
J
LONG
F
FLOAT
V
VOID
D
DOUBLE
L полное квалифицированное имя
класса
полное квалифицированное имя
класса
[ тип
тип[]
(типы аргументов) возвращаемый тип
полная сигнатура метода
SIGNATURE - примеры



метод LONG M1(INT N, STRING S, INT[] ARR);
• сигнатура (ILJAVA/LANG/STRING;[I)J;
метод VOID M2(FLOAT N, BYTE[][] ARR, RUNTIME R);
• сигнатура (F[[BLJAVA/LANG/RUNTIME;)V.
Метод void funcC()
• сигнатура ()V
Правила формирования имени
С/С++ - функции
Формируется путем последовательного соединения
следующих компонентов:
•
•
•
•
•
префикс JAVA_
полное квалифицированное имя класса;
символ подчеркивания ("_")
имя метода
для перегружаемых (OVERLOADED) методов
- два символа подчеркивания ("_ _") с
последующей сигнатурой метода.
Реализации выполнения native
метода
#include …
#include “HelloWorld.h“
JNIEXPORT VOID JNICALL Java_displayHello_helloWorld
(JNIEnv * je, jobject jo) {
printf( "!!! In the native method !!!\n" );
return;
}
Типы и структуры данных JNI



Все типы описаны в файле JNI.H
JNI.H использует стандартную технику
препроцессирования с макросом _CPLUSPLUS
В зависимости от того, какой (С++ или С) код
компилируется, будут создаваться две немного
отличающиеся версии описания типов.
Каждая из них требует определенного синтаксиса
доступа.
Доступа к функциям JNI
Стиль С
• JNIEXPORT VOID JNICALL
JAVA_SYSTEMSPECIFIC_DOSPECIFIC(JNIENV* ENV,
JOBJECT THIS) {
JINT VERSION = (*ENV)->GETVERSION(ENV);
Е
}
Стиль С++
• JNIEXPORT VOID JNICALL
JAVA_SYSTEMSPECIFIC_DOSPECIFIC(JNIENV* ENV,
JOBJECT THIS) {
JINT VERSION = ENV->GETVERSION();
Е
}
Продолжение следует…
Development Tool for Java-COM Bridge
( RJCB
in JVI)
Download