Spec-Zone .ru
спецификации, руководства, описания, API
|
Содержание | Предыдущий |
API Вызова позволяет поставщикам программного обеспечения загружать Java VM в произвольное собственное приложение. Поставщики могут поставить поддерживающие Java приложения, не имея необходимость соединять с Java исходный код VM.
Эта глава начинается с краткого обзора API Вызова. Это сопровождается ссылочными страницами для всех API-функций Вызова.
Следующий пример кода иллюстрирует, как использовать функции в API Вызова. В этом примере код C++ создает Java VM и вызывает статический метод, вызванный Main.test
. Для ясности мы опускаем проверку на ошибки.
#include <jni.h> /* where everything is defined */ ... JavaVM *jvm; /* denotes a Java VM */ JNIEnv *env; /* pointer to native method interface */ JavaVMInitArgs vm_args; /* JDK/JRE 6 VM initialization arguments */ JavaVMOption* options = new JavaVMOption[1]; options[0].optionString = "-Djava.class.path=/usr/lib/java"; vm_args.version = JNI_VERSION_1_6; vm_args.nOptions = 1; vm_args.options = options; vm_args.ignoreUnrecognized = false; /* load and initialize a Java VM, return a JNI interface * pointer in env */ JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); delete options; /* invoke the Main.test method using the JNI */ jclass cls = env->FindClass("Main"); jmethodID mid = env->GetStaticMethodID(cls, "test", "(I)V"); env->CallStaticVoidMethod(cls, mid, 100); /* We are done. */ jvm->DestroyJavaVM();
Этот пример использует три функции в API. API Вызова позволяет собственному приложению использовать указатель на интерфейс JNI для доступа функции VM. Проект подобен JRI Netscape, Встраивающему Интерфейс.
JNI_CreateJavaVM()
функционируйте загружает и инициализирует Java VM и возвращает указатель на указатель на интерфейс JNI. Поток, который вызывал JNI_CreateJavaVM()
как полагают, основной поток.
Указатель на интерфейс JNI (JNIEnv
) допустимо только в текущем потоке. Если другой поток должен получить доступ к Java VM, это должно сначала вызвать AttachCurrentThread()
присоединиться к VM и получить указатель на интерфейс JNI. После того, как присоединенный к VM, собственный поток работает точно так же как обычное выполнение потока Java в собственном методе. Собственный поток остается присоединенным к VM, пока это не вызывает DetachCurrentThread()
отсоединять себя.
У присоединенного потока должно быть достаточное стековое пространство, чтобы выполнить разумный объем работы. Выделение стекового пространства на поток работает специфичный для системы. Например, используя pthreads, размер стека может быть определен в pthread_attr_t
параметр pthread_create
.
Собственный поток, присоединенный к VM, должен вызвать DetachCurrentThread()
отсоединять себя перед выходом. Поток не может отсоединить себя, если есть методы Java на стеке вызовов.
JNI_DestroyJavaVM()
функция разгружает Java VM. С JDK/JRE 1.1, только основной поток мог разгрузить VM, вызывая DestroyJavaVM
. С JDK/JRE 1.2, было удалено ограничение, и любой поток может вызвать DestroyJavaVM
разгрузить VM.
VM ожидает, пока текущий поток не является единственным пользовательским потоком недемона прежде, чем это фактически разгрузится. Пользовательские потоки включают и потоки Java и присоединили собственные потоки. Это ограничение существует, потому что поток Java или присоединил собственный поток, может содержать системные ресурсы, такие как блокировки, окна, и так далее. VM
не может автоматически освободить эти ресурсы. Ограничивая текущий поток, чтобы быть единственным рабочим потоком, когда VM разгружается, бремя выпуска системных ресурсов, сохраненных произвольными потоками, находится на программисте.
С JDK/JRE 1.2, каждый загрузчик class управляет своим собственным набором собственных библиотек. Тот же самый JNI собственная библиотека не может быть загружен больше чем в один загрузчик class. Выполнение так причины UnsatisfiedLinkError
быть брошенным. Например, System.loadLibrary
броски UnsatisfiedLinkError
когда использующийся загрузить собственную библиотеку в два загрузчика class. Преимущества нового подхода:
Чтобы облегчить управление версиями и управление ресурсами, библиотеки JNI с JDK/JRE 1.2 дополнительно экспортируют следующие две функции:
jint JNI_OnLoad(JavaVM *vm, void *reserved);
JNI_OnLoad
когда собственная библиотека загружается (например, через System.loadLibrary
). JNI_OnLoad
должен возвратить версию JNI, необходимую собственной библиотеке. Чтобы использовать любую из новых функций JNI, собственная библиотека должна экспортировать a JNI_OnLoad
функция, которая возвращается JNI_VERSION_1_2
. Если собственная библиотека не экспортирует a JNI_OnLoad
функция, VM предполагает, что библиотека только требует версии JNI JNI_VERSION_1_1
. Если VM не распознает номер версии, возвращенный JNI_OnLoad
, собственная библиотека не может быть загружена.
Экспортируемый от собственных библиотек, которые содержат собственную реализацию метода.
JDK/JRE 1.4
Чтобы использовать функции JNI, представленные в выпуске 1.2 J2SE, в дополнение к тем, которые были доступны в JDK/JRE 1.1, собственная библиотека должна экспортировать a JNI_OnLoad
функция, которая возвращается JNI_VERSION_1_2
.
Чтобы использовать функции JNI, представленные в выпуске 1.4 J2SE, в дополнение к тем, которые были доступны в выпуске 1.2, собственная библиотека должна экспортировать a JNI_OnLoad
функция, которая возвращается JNI_VERSION_1_4
.
Если собственная библиотека не экспортирует a JNI_OnLoad
функция, VM предполагает, что библиотека только требует версии JNI JNI_VERSION_1_1
. Если VM не распознает номер версии, возвращенный JNI_OnLoad
, собственная библиотека не может быть загружена.
void JNI_OnUnload(JavaVM *vm, void *reserved);
JNI_OnUnload
когда загрузчик class, содержащий собственную библиотеку, собирается "мусор". Эта функция может использоваться, чтобы выполнить операции уборки. Поскольку эта функция вызывается в неизвестном контексте (такой как от финализатора), программист должен быть консервативным при использовании Java службы VM, и рефрен от произвольных обратных вызовов Java. Отметьте это JNI_OnLoad
и JNI_OnUnload
две функции, дополнительно предоставленные библиотеками JNI, не экспортируемыми от VM.
JavaVM
тип является указателем на таблицу API-функции Вызова. Следующий пример кода показывает эту функциональную таблицу.
typedef const struct JNIInvokeInterface *JavaVM; const struct JNIInvokeInterface ... = { NULL, NULL, NULL, DestroyJavaVM, AttachCurrentThread, DetachCurrentThread, GetEnv, AttachCurrentThreadAsDaemon };
Отметьте что три API-функции Вызова, JNI_GetDefaultJavaVMInitArgs()
, JNI_GetCreatedJavaVMs()
, и JNI_CreateJavaVM()
, не часть таблицы функции JavaVM. Эти функции могут использоваться без существования ранее JavaVM
структура.
jint JNI_GetDefaultJavaVMInitArgs(void *vm_args);
Возвращает конфигурацию значения по умолчанию для Java VM. Прежде, чем вызвать эту функцию, собственный код должен установить vm_args-> поле версии к версии JNI, которую это ожидает, что VM будет поддерживать. После этой функции возвраты vm_args-> версия будет установлена в фактическую версию JNI, которую поддерживает VM.
Экспортируемый от собственной библиотеки, которая реализует виртуальную машину Java.
vm_args
: указатель на a JavaVMInitArgs
структура в, к которому параметры по умолчанию заполнены.
Возвраты JNI_OK
если требуемая версия поддерживается; возвращает код ошибки JNI (отрицательное число), если требуемая версия не поддерживается.
jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs);
Возвраты весь Java VMs, которые были созданы. Указатели на VMs пишутся в буфере vmBuf в порядке, они создаются. В большинстве bufLen числа записей будет записан. Общее количество создаваемого VMs возвращается в *nVMs.
С JDK/JRE 1.2, не поддерживается создание многократного VMs в единственном процессе.
Экспортируемый от собственной библиотеки, которая реализует виртуальную машину Java.
vmBuf
: указатель на буфер, куда структуры VM будут помещены.
bufLen
: длина буфера.
nVMs
: указатель на целое число.
Возвраты JNI_OK
на успехе; возвращает подходящий код ошибки JNI (отрицательное число) при отказе.
jint JNI_CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args);
Загрузки и инициализируют Java VM. Текущий поток становится основным потоком. Наборы env
параметр указателю на интерфейс JNI основного потока.
Второй параметр JNI_CreateJavaVM
всегда указатель на JNIEnv *
, в то время как третьим параметром является указатель на a JavaVMInitArgs
структура, которая использует строки опции, чтобы закодировать произвольные опции запуска VM:
typedef struct JavaVMInitArgs { jint version; jint nOptions; JavaVMOption *options; jboolean ignoreUnrecognized; } JavaVMInitArgs;
version
поле должно быть установлено в, по крайней мере, JNI_VERSION_1_2
. options
поле является массивом следующего типа:
typedef struct JavaVMOption { char *optionString; /* the option as a string in the default platform encoding */ void *extraInfo; } JavaVMOption;
Размер массива обозначается nOptions полем в JavaVMInitArgs
. Если ignoreUnrecognized
JNI_TRUE
, JNI_CreateJavaVM
проигнорируйте все нераспознанные строки опции, которые начинаются"-X
"или"_
". Если ignoreUnrecognized
JNI_FALSE
, JNI_CreateJavaVM
возвраты JNI_ERR
как только это встречается с любыми нераспознанными строками опции. Весь Java VMs должен распознать следующий набор стандартных опций:
optionString | значение |
---|---|
-D<name>=<value> |
Установите системное свойство |
-verbose[:class|gc|jni] |
Включите многословному выводу. Опции могут сопровождаться списком разделенных запятой значений имен, указывающих, какие сообщения будут напечатаны VM. Например,"-verbose:gc,class "дает VM команду печатать GC и class, загружающий похожие сообщения. Стандартные имена включают: gc , class , и jni . Все нестандартное (VM-specific) имена должно начаться"X ". |
vfprintf |
extraInfo указатель на vfprintf рычаг. |
exit |
extraInfo указатель на exit рычаг. |
abort |
extraInfo указатель на abort рычаг. |
Кроме того, каждая реализация VM может поддерживать свой собственный набор нестандартных строк опции. Нестандартные имена опции должны начаться"-X
"или подчеркивание ("_
"). Например, JDK/JRE поддерживает -Xms
и -Xmx
опции, чтобы позволить программистам определяют начальный и максимальный размер "кучи". Опции, которые начинаются"-X
"доступны от"java
"командная строка.
Вот пример кода, который создает Java VM в JDK/JRE:
JavaVMInitArgs vm_args; JavaVMOption options[4]; options[0].optionString = "-Djava.compiler=NONE"; /* disable JIT */ options[1].optionString = "-Djava.class.path=c:\myclasses"; /* user classes */ options[2].optionString = "-Djava.library.path=c:\mylibs"; /* set native library path */ options[3].optionString = "-verbose:jni"; /* print JNI-related messages */ vm_args.version = JNI_VERSION_1_2; vm_args.options = options; vm_args.nOptions = 4; vm_args.ignoreUnrecognized = TRUE; /* Note that in the JDK/JRE, there is no longer any need to call * JNI_GetDefaultJavaVMInitArgs. */ res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args); if (res < 0) ...
Экспортируемый от собственной библиотеки, которая реализует виртуальную машину Java.
p_vm
: указатель на расположение, куда получающаяся структура VM будет помещена.
p_env
: указатель на расположение, куда указатель на интерфейс JNI для основного потока будет помещен.
vm_args
: Java параметры инициализации VM.
Возвраты JNI_OK
на успехе; возвращает подходящий код ошибки JNI (отрицательное число) при отказе.
jint DestroyJavaVM(JavaVM *vm);
Разгружает Java VM и исправляет его ресурсы.
Поддержка DestroyJavaVM
не было полно в JDK/JRE 1.1. С JDK/JRE 1.1 Только основной поток может вызвать DestroyJavaVM
. Начиная с JDK/JRE 1.2, любой поток, или присоединенный или нет, может вызвать эту функцию. Если текущий поток присоединяется, VM ожидает, пока текущий поток не является единственным недемоном поток Java на уровне пользователя. Если текущий поток не присоединяется, VM присоединяет текущий поток и затем ожидает, пока текущий поток не является единственным недемоном поток на уровне пользователя. JDK/JRE все еще не поддерживает разгрузку VM, как бы то ни было.
Индексируйте 3 в таблице функции интерфейса JavaVM.
vm
: VM Java, который будет уничтожен.
Возвраты JNI_OK
на успехе; возвращает подходящий код ошибки JNI (отрицательное число) при отказе.
С JDK/JRE не поддерживаются 1.1.2 разгрузки VM.
jint AttachCurrentThread(JavaVM *vm, void **p_env, void *thr_args);
Присоединяет текущий поток к Java VM. Возвращает указатель на интерфейс JNI в JNIEnv
параметр.
Попытка присоединить поток, который уже присоединяется, нет.
Собственный поток не может быть присоединен одновременно к двум Java VMs.
Когда поток присоединен к VM, контексту, загрузчик class является программой начальной загрузки.
Индексируйте 4 в таблице функции интерфейса JavaVM.
vm
: VM, к которому будет присоединен текущий поток.
p_env
: указатель на расположение, куда указатель на интерфейс JNI текущего потока будет помещен.
thr_args
: может быть НУЛЬ или указатель на a JavaVMAttachArgs
структура, чтобы определить дополнительную информацию:
С JDK/JRE 1.1, второго параметра AttachCurrentThread
всегда указатель на JNIEnv
. Третий параметр AttachCurrentThread
был зарезервирован, и должен быть установлен в NULL
.
С JDK/JRE 1.2, Вы передаете NULL
как третий параметр за 1.1 поведения, или передача указатель на следующую структуру, чтобы определить дополнительную информацию:
typedef struct JavaVMAttachArgs { jint version; /* must be at least JNI_VERSION_1_2 */ char *name; /* the name of the thread as a modified UTF-8 string, or NULL */ jobject group; /* global ref of a ThreadGroup object, or NULL */ } JavaVMAttachArgs
Возвраты JNI_OK
на успехе; возвращает подходящий код ошибки JNI (отрицательное число) при отказе.
jint AttachCurrentThreadAsDaemon(JavaVM* vm, void** penv, void* args);
Та же самая семантика как AttachCurrentThread, но недавно создаваемый экземпляр java.lang.Thread является демоном.
Если поток был уже присоединен или через AttachCurrentThread или через AttachCurrentThreadAsDaemon, эта подпрограмма просто устанавливает значение, на которое указывает penv к JNIEnv текущего потока. В этом случае ни AttachCurrentThread, ни эта подпрограмма не имеют эффекта на состояние демона потока.
Индексируйте 7 в таблице функции интерфейса JavaVM.
vm: экземпляр виртуальной машины, к которому будет присоединен текущий поток.
penv: указатель на расположение, в которое будет помещен указатель на интерфейс JNIEnv для текущего потока.
args: указатель на структуру JavaVMAttachArgs.
Возвраты JNI_OK
на успехе; возвращает подходящий код ошибки JNI (отрицательное число) при отказе.
Ни один.
JDK/JRE 1.4
jint DetachCurrentThread(JavaVM *vm);
Отсоединяет текущий поток от Java VM. Выпускаются все мониторы Java, сохраненные этим потоком. Уведомляются все потоки Java, ожидающие этого потока, чтобы умереть.
С JDK/JRE 1.2, основной поток может быть отсоединен от VM.Индексируйте 5 в таблице функции интерфейса JavaVM.
vm
: VM, от которого будет отсоединен текущий поток.
Возвраты JNI_OK
на успехе; возвращает подходящий код ошибки JNI (отрицательное число) при отказе.
jint GetEnv(JavaVM *vm, void **env, jint version);
Индексируйте 6 в таблице функции интерфейса JavaVM.
vm
: Экземпляр виртуальной машины, от которого будет получен интерфейс.env
: указатель на расположение, куда указатель на интерфейс JNI для текущего потока будет помещен.version
: Требуемая версия JNI.Если текущий поток не присоединен к VM, наборам *env
к NULL
, и возвраты JNI_EDETACHED
. Если указанная версия не поддерживается, наборы *env
к NULL
, и возвраты JNI_EVERSION
. Иначе, наборы *env
к соответствующему интерфейсу, и возвратам JNI_OK
.
JDK/JRE 1.2
Содержание | Предыдущий |