Spec-Zone .ru
спецификации, руководства, описания, API
Содержание документации
Содержание | Предыдущий

API Вызова


 Глава 5

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, Встраивающему Интерфейс.

Создание VM

JNI_CreateJavaVM() функционируйте загружает и инициализирует Java VM и возвращает указатель на указатель на интерфейс JNI. Поток, который вызывал JNI_CreateJavaVM() как полагают, основной поток.

Присоединение к VM

Указатель на интерфейс JNI (JNIEnv) допустимо только в текущем потоке. Если другой поток должен получить доступ к Java VM, это должно сначала вызвать AttachCurrentThread() присоединиться к VM и получить указатель на интерфейс JNI. После того, как присоединенный к VM, собственный поток работает точно так же как обычное выполнение потока Java в собственном методе. Собственный поток остается присоединенным к VM, пока это не вызывает DetachCurrentThread() отсоединять себя.

У присоединенного потока должно быть достаточное стековое пространство, чтобы выполнить разумный объем работы. Выделение стекового пространства на поток работает специфичный для системы. Например, используя pthreads, размер стека может быть определен в pthread_attr_t параметр pthread_create.

Отсоединение от VM

Собственный поток, присоединенный к VM, должен вызвать DetachCurrentThread() отсоединять себя перед выходом. Поток не может отсоединить себя, если есть методы Java на стеке вызовов.

Разгрузка VM

JNI_DestroyJavaVM() функция разгружает Java VM. С JDK/JRE 1.1, только основной поток мог разгрузить VM, вызывая DestroyJavaVM. С JDK/JRE 1.2, было удалено ограничение, и любой поток может вызвать DestroyJavaVM разгрузить VM.

VM ожидает, пока текущий поток не является единственным пользовательским потоком недемона прежде, чем это фактически разгрузится. Пользовательские потоки включают и потоки Java и присоединили собственные потоки. Это ограничение существует, потому что поток Java или присоединил собственный поток, может содержать системные ресурсы, такие как блокировки, окна, и так далее. VM не может автоматически освободить эти ресурсы. Ограничивая текущий поток, чтобы быть единственным рабочим потоком, когда VM разгружается, бремя выпуска системных ресурсов, сохраненных произвольными потоками, находится на программисте.

Библиотека и управление Версией

С JDK/JRE 1.1, как только собственная библиотека загружается, это видимо от всех загрузчиков class. Поэтому два класса в различных загрузчиках class могут соединиться с тем же самым собственным методом. Это приводит к двум проблемам:

С JDK/JRE 1.2, каждый загрузчик class управляет своим собственным набором собственных библиотек. Тот же самый JNI собственная библиотека не может быть загружен больше чем в один загрузчик class. Выполнение так причины UnsatisfiedLinkError быть брошенным. Например, System.loadLibrary броски UnsatisfiedLinkError когда использующийся загрузить собственную библиотеку в два загрузчика class. Преимущества нового подхода:

Чтобы облегчить управление версиями и управление ресурсами, библиотеки JNI с JDK/JRE 1.2 дополнительно экспортируют следующие две функции:

JNI_OnLoad

jint JNI_OnLoad(JavaVM *vm, void *reserved);

Вызовы VM 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, собственная библиотека не может быть загружена.

JNI_OnUnload

void JNI_OnUnload(JavaVM *vm, void *reserved);

Вызовы VM JNI_OnUnload когда загрузчик class, содержащий собственную библиотеку, собирается "мусор". Эта функция может использоваться, чтобы выполнить операции уборки. Поскольку эта функция вызывается в неизвестном контексте (такой как от финализатора), программист должен быть консервативным при использовании Java службы VM, и рефрен от произвольных обратных вызовов Java.

Отметьте это JNI_OnLoad и JNI_OnUnload две функции, дополнительно предоставленные библиотеками JNI, не экспортируемыми от VM.

РЕДАКТИРОВАНИЕ:

Экспортируемый от собственных библиотек, которые содержат собственную реализацию метода.

API-функции вызова

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 структура.

JNI_GetDefaultJavaVMInitArgs

jint JNI_GetDefaultJavaVMInitArgs(void *vm_args);

Возвращает конфигурацию значения по умолчанию для Java VM. Прежде, чем вызвать эту функцию, собственный код должен установить vm_args-> поле версии к версии JNI, которую это ожидает, что VM будет поддерживать. После этой функции возвраты vm_args-> версия будет установлена в фактическую версию JNI, которую поддерживает VM.

РЕДАКТИРОВАНИЕ:

Экспортируемый от собственной библиотеки, которая реализует виртуальную машину Java.

ПАРАМЕТРЫ:

vm_args: указатель на a JavaVMInitArgs структура в, к которому параметры по умолчанию заполнены.

ВОЗВРАТЫ:

Возвраты JNI_OK если требуемая версия поддерживается; возвращает код ошибки JNI (отрицательное число), если требуемая версия не поддерживается.

JNI_GetCreatedJavaVMs

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 (отрицательное число) при отказе.

JNI_CreateJavaVM

jint JNI_CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args);

Загрузки и инициализируют Java VM. Текущий поток становится основным потоком. Наборы env параметр указателю на интерфейс JNI основного потока.

С JDK/JRE 1.2, не поддерживается создание многократного VMs в единственном процессе.

Второй параметр 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 (отрицательное число) при отказе.

DestroyJavaVM

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.

AttachCurrentThread

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 (отрицательное число) при отказе.

AttachCurrentThreadAsDaemon

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

DetachCurrentThread

jint DetachCurrentThread(JavaVM *vm);

Отсоединяет текущий поток от Java VM. Выпускаются все мониторы Java, сохраненные этим потоком. Уведомляются все потоки Java, ожидающие этого потока, чтобы умереть.

С JDK/JRE 1.2, основной поток может быть отсоединен от VM.

РЕДАКТИРОВАНИЕ:

Индексируйте 5 в таблице функции интерфейса JavaVM.

ПАРАМЕТРЫ:

vm: VM, от которого будет отсоединен текущий поток.

ВОЗВРАТЫ:

Возвраты JNI_OK на успехе; возвращает подходящий код ошибки JNI (отрицательное число) при отказе.

GetEnv

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

 


Содержание | Предыдущий

Oracle и/или его филиалы Авторское право © 1993, 2012, Oracle и/или его филиалы. Все права защищены.
Свяжитесь с Нами