|
Spec-Zone .ru
спецификации, руководства, описания, API
|
JNI был улучшен в Java 2 SDK к:
#define JNI_VERSION_1_1 0x00010001 #define JNI_VERSION_1_2 0x00010002 /* Error codes */ #define JNI_EDETACHED (-2) /* thread detached from the VM */ #define JNI_EVERSION (-3) /* JNI version error */
FindClass был расширен так, чтобы это сочло классы загруженными загрузчиком class.
jclass FindClass(JNIEnv *env, const char *name);
В JDK 1.1, FindClass искавшие только локальные классы в CLASSPATH. У получающихся классов не было загрузчика class.
Модель обеспечения безопасности Java была расширена, чтобы позволить несистемным классам загружать и вызывать собственные методы. В Java 2 Платформы, FindClass определяет местоположение загрузчика class, связанного с текущим собственным методом. Если собственный код будет принадлежать системе class, то никакой загрузчик class не будет включен. Иначе, надлежащий загрузчик class будет вызван, чтобы загрузить и соединить именованный class.
Когда FindClass вызывается через Интерфейс Вызова, нет никакого текущего собственного метода или его связанного загрузчика class. В этом случае, результат ClassLoader.getBaseClassLoader используется. Это - загрузчик class, который виртуальная машина создает для приложений, и в состоянии определить местоположение классов, перечисленных в java.class.path свойство.
В Java 2 SDK каждый загрузчик class управляет своим собственным набором собственных библиотек. Тот же самый JNI собственная библиотека не может быть загружен больше чем в один загрузчик class. Выполнение так причины UnsatisfiedLinkError быть брошенным. Например, System.loadLibrary броски UnsatisfiedLinkError когда использующийся загрузить собственную библиотеку в два загрузчика class. Преимущества нового подхода:
Чтобы облегчить управление управлением версиями и управление ресурсами, библиотеки JNI в Java, 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, собственная библиотека не может быть загружена.
void JNI_OnUnload(JavaVM *vm, void *reserved);
JNI_OnUnload когда загрузчик class, содержащий собственную библиотеку, собирается "мусор". Эта функция может использоваться, чтобы выполнить операции уборки. Поскольку эта функция вызывается в неизвестном контексте (такой как от финализатора), программист должен быть консервативным при использовании Java службы VM, и рефрен от произвольных обратных вызовов Java. Отметьте это JNI_OnLoad и JNI_OnUnload две функции, дополнительно предоставленные библиотеками JNI, не экспортируемыми от VM.
JDK 1.1 обеспечивает a DeleteLocalRef функционируйте так, чтобы программисты могли вручную удалить локальные ссылки. Например, если собственный код выполняет итерации через потенциально многочисленный массив объектов и использует один элемент в каждой итерации, это - хорошая практика, чтобы удалить локальную ссылку на больше используемый элемент массива прежде, чем новая локальная ссылка будет создана в следующей итерации.
Java 2 SDK обеспечивает дополнительный набор функций для локального ссылочного управления временем жизни.
jint EnsureLocalCapacity(JNIEnv *env, jint capacity);
Гарантирует, что, по крайней мере, данное число локальных ссылок может быть создано в текущем потоке. Возвраты 0 на успехе; иначе возвращает отрицательное число и бросает OutOfMemoryError.
Прежде, чем это введет собственный метод, VM автоматически гарантирует, что могут быть созданы по крайней мере 16 локальных ссылок.
Для обратной совместимости VM выделяет локальные ссылки вне обеспеченной емкости. (Как поддержка отладки, VM может дать пользовательские предупреждения, что создаются слишком много локальных ссылок. В Java 2 SDK программист может предоставить -verbose:jni параметр командной строки, чтобы включить эти сообщения.) Вызовы VM FatalError если больше локальных ссылок не может быть создано вне обеспеченной емкости.
jint PushLocalFrame(JNIEnv *env, jint capacity);
Создает новый локальный ссылочный фрейм, в котором может быть создано, по крайней мере, данное число локальных ссылок. Возвраты 0 на успехе, отрицательном числе и ожидании OutOfMemoryError при отказе.
Отметьте, что локальные ссылки, уже создаваемые в предыдущих локальных фреймах, все еще допустимы в текущем локальном фрейме.
jobject PopLocalFrame(JNIEnv *env, jobject result);
Появляется от текущего локального ссылочного фрейма, освобождает все локальные ссылки, и возвращает локальную ссылку в предыдущем локальном ссылочном фрейме для данного result объект.
Передача NULL как result если Вы не должны возвратить ссылку на предыдущий фрейм.
jobject NewLocalRef(JNIEnv *env, jobject ref);
ref. Данный ref может быть глобальная или локальная ссылка. Возвраты NULL если ref обращается к null.
jboolean ExceptionCheck(JNIEnv *env);
JNI_TRUE когда есть исключение на ожидании; иначе, возвраты JNI_FALSE.
NULL. Программисты могут обнаружить ли слабые глобальные контрольные точки к освобожденному объекту при использовании IsSameObject сравнить слабую ссылку с NULL. Слабые глобальные ссылки в JNI являются упрощенной версией Слабых ссылок Java, доступных как часть Java 2 API Платформы ( java.lang.ref пакет и его классы).
Разъяснение (добавленный июнь 2001)
Так как сборка "мусора" может произойти, в то время как собственные методы работают, объекты, упомянутые слабыми глобальными ссылками, могут быть освобождены в любое время. В то время как слабые глобальные ссылки могут использоваться, где глобальные ссылки используются, обычно неуместно сделать так, поскольку они могут стать функционально эквивалентными NULL
без уведомления.
В то время как IsSameObject может использоваться, чтобы определить, обращается ли слабая глобальная ссылка к освобожденному объекту, она не препятствует объекту быть освобожденным сразу после того. Следовательно, программисты, возможно, не полагаются на эту проверку, чтобы определить, может ли слабая глобальная ссылка используемый (как не -NULL ссылка) в любом будущем вызове функции JNI.
Чтобы преодолеть это свойственное ограничение, рекомендуется, чтобы стандарт (strong) локальная или глобальная ссылка на тот же самый объект был получен, используя функции JNI NewLocalRef
или NewGlobalRef, и что эта ссылка strong использоваться, чтобы получить доступ к намеченному объекту. Эти функции возвратятся NULL если объект был освобожден, и иначе возвратит ссылку strong (который будет препятствовать объекту быть освобожденным). Новая ссылка должна быть явно удалена, когда немедленный доступ к объекту больше не требуется, позволяя объект быть освобожденным.
Слабая глобальная ссылка более слаба чем другие типы слабых ссылок (объекты Java классов SoftReference или WeakReference). Слабая глобальная ссылка на конкретную цель не будет становиться функционально эквивалентной NULL пока SoftReference или объектам WeakReference, обращающимся к той же самой конкретной цели, не очистили их ссылки.
Слабая глобальная ссылка более слаба чем внутренние ссылки Java на объекты, требующие завершения. Слабая глобальная ссылка не будет становиться функционально эквивалентной
NULL до окончания завершения финализатора для объекта, на который ссылаются, если существующий.
Взаимодействия между слабыми глобальными ссылками и PhantomReferences неопределены. В частности реализации Java VM может (или не может) обрабатывать слабые глобальные ссылки после PhantomReferences, и это может (или не может), будьте возможны, чтобы использовать слабые глобальные ссылки, чтобы держаться за объекты, который также упоминаетесь объектами PhantomReference. Этого неопределенного использования слабых глобальных ссылок нужно избежать.
jweak NewWeakGlobalRef(JNIEnv *env, jobject obj);
NULL если obj обращается к null, или если VM исчерпывает память. Если VM исчерпывает память, OutOfMemoryError будет брошен.
void DeleteWeakGlobalRef(JNIEnv *env, jweak obj);
В JDK 1.1, программисты могут использовать Get/Release<PrimitiveType>ArrayElements функции, чтобы получить указатель на примитивные элементы массива. Если VM поддерживает прикрепление, указатель на исходные данные возвращается; иначе, копия делается.
Новые функции позволяют собственному коду получать прямой указатель, чтобы выстроить элементы, даже если VM не поддерживает прикрепление.
void * GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy);
void ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode);
Get/Release<PrimitiveType>ArrayElements функции. Если возможный, VM возвращает указатель на примитивный массив; иначе, копия делается. Однако, есть существенные ограничения на то, как эти функции могут использоваться.
После вызова GetPrimitiveArrayCritical, собственный код не должен работать за длительным периодом времени прежде, чем это вызовет ReleasePrimitiveArrayCritical. Мы должны обработать код в этой паре функций как работающий в "критической области." В критической области собственный код не должен вызвать другие функции JNI, или любой системный вызов, который может заставить текущий поток блокировать и ожидать другого потока Java. (Например, текущий поток не должен вызвать read на потоке, записанном другим потоком Java.)
Эти ограничения делают это более вероятно, что собственный код получит нескопированную версию массива, даже если VM не будет поддерживать прикрепление. Например, VM может временно отключить сборку "мусора", когда собственный код содержит указатель на массив, полученный через GetPrimitiveArrayCritical.
Многократные пары GetPrimtiveArrayCritical и ReleasePrimitiveArrayCritical может быть вложен. Например:
jint len = (*env)->GetArrayLength(env, arr1);
jbyte *a1 = (*env)->GetPrimitiveArrayCritical(env, arr1, 0);
jbyte *a2 = (*env)->GetPrimitiveArrayCritical(env, arr2, 0);
/* We need to check in case the VM tried to make a copy. */
if (a1 == NULL || a2 == NULL) {
... /* out of memory exception thrown */
}
memcpy(a1, a2, len);
(*env)->ReleasePrimitiveArrayCritical(env, arr2, a2, 0);
(*env)->ReleasePrimitiveArrayCritical(env, arr1, a1, 0);
Отметьте это GetPrimitiveArrayCritical мог бы все еще сделать копию массива, если VM внутренне представляет массивы в различном формате. Поэтому мы должны проверить его возвращаемое значение по NULL для возможного из ситуаций с памятью.
void GetStringRegion(JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf);
len число символов Unicode, начинающихся при смещении start к данному буферу buf. Броски StringIndexOutOfBoundsException на индексируют переполнение.
< void GetStringUTFRegion(JNIEnv *env, jstring str, jsize start, jsize len, char *buf);
len число символов Unicode, начинающихся при смещении start в UTF-8 форматируют и помещают результат в данный буфер buf. Броски StringIndexOutOfBoundsException на индексируют переполнение.
const jchar * GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy);
void ReleaseStringCritical(JNIEnv *env, jstring string, const jchar *carray);
Get/ReleaseStringChars функции. Если возможный, VM возвращает указатель, чтобы представить элементы в виде строки; иначе, копия делается. Однако, есть существенные ограничения на то, как эти функции могут использоваться. В сегменте кода, включенном Get/ReleaseStringCritical вызовы, собственный код не должен издать произвольные приказы JNI, или заставить текущий поток блокировать. Ограничения на Get/ReleaseStringCritical подобны тем на Get/ReleasePrimitiveArrayCritical.
Программисты могут использовать JNI, чтобы вызвать методы Java или поля Java доступа, если они знают имя и тип методов или полей. API Reflection Ядра Java позволяет программистам анализировать классы Java во времени выполнения. JNI обеспечивает ряд функций преобразования между полем и ID метода, привыкшими в JNI к полю и объектам метода, используемым в API Reflection Ядра Java.
jmethodID FromReflectedMethod(JNIEnv *env, jobject method);
java.lang.reflect.Method или java.lang.reflect.Constructor возразите против ID метода.
jfieldID FromReflectedField(JNIEnv *env, jobject field);
java.lang.reflect.Field к полевому ID.
jobject ToReflectedMethod(JNIEnv *env, jclass cls,
jmethodID methodID);
cls к a java.lang.reflect.Method или java.lang.reflect.Constructor объект. Броски OutOfMemoryError и возвраты 0, если сбои.
jobject ToReflectedField(JNIEnv *env, jclass cls,
jfieldID fieldID);
cls к a java.lang.reflect.Field объект. Броски OutOfMemoryError и возвраты 0, если сбои.
jint JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args);
JNI_CreateJavaVM всегда указатель на JNIEnv *. Третьим параметром является указатель на JDK 1.1 определенных структуры (JDK1_1InitArgs). JDK1_1InitArgs структура ясно не разрабатывается, чтобы быть переносимой на всем VMs. В Java 2 SDK мы представляем стандартную структуру инициализации VM. Обратная совместимость сохраняется. Если параметр инициализации VM указывает на a JDK1_1InitArgs структура, JNI_CreateJavaVM все еще возвращает 1.1 версии указателя на интерфейс JNI. VM возвращает 1.2 версии указателя на интерфейс JNI, если третий параметр указывает на a JavaVMInitArgs структура. В отличие от этого JDK1_1InitArgs, который содержит фиксированный набор опций, JavaVMInitArgs опция использования представляет в виде строки, чтобы закодировать произвольные опции запуска VM.
typedef struct JavaVMInitArgs {
jint version;
jint nOptions;
JavaVMOption *options;
jboolean ignoreUnrecognized;
} JavaVMInitArgs;
version поле должно быть установлено в JNI_VERSION_1_2. (Напротив, поле версии в JDK1_1InitArgs должен быть установлен в JNI_VERSION_1_1.) options поле является массивом следующего типа:
typedef struct JavaVMOption {
char *optionString;
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"или подчеркивание ("_"). Например, Java 2 SDK поддерживает -Xms и -Xmx опции, чтобы позволить программистам определяют начальный и максимальный размер "кучи". Опции, которые начинаются"-X"доступны от"java"командная строка.
Вот пример кода, который создает Java VM в Java 2 SDK:
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 Java 2 SDK, there is no longer any need to call * JNI_GetDefaultJavaVMInitArgs. */ res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args); if (res < 0) ...
Java 2 SDK все еще поддерживает JDK1_1InitArgs точно таким же образом как JDK 1.1.
jint AttachCurrentThread(JavaVM *vm, void **penv, void *args);
AttachCurrentThread всегда указатель на JNIEnv. Третий параметр AttachCurrentThread был зарезервирован, и должен быть установлен в NULL. В Java 2 SDK Вы передаете NULL как третий параметр за 1.1 поведения, или передача указатель на следующую структуру, чтобы определить дополнительную информацию:
typedef struct JavaVMAttachArgs {
jint version; /* must be JNI_VERSION_1_2 */
char *name; /* the name of the thread, or NULL */
jobject group; /* global ref of a ThreadGroup object, or NULL */
} JavaVMAttachArgs;
jint DetachCurrentThread(JavaVM *vm);
DestroyJavaVM разгрузить весь VM. В Java 2 SDK основной поток может быть отсоединен от VM.
jint DestroyJavaVM(JavaVM *vm);
DestroyJavaVM не было полно в 1.1. Только основной поток может вызвать DestroyJavaVM. В Java 2 SDK любой поток, или присоединенный или нет, может вызвать эту функцию. Если текущий поток присоединяется, VM ожидает, пока текущий поток не является единственным потоком Java на уровне пользователя. Если текущий поток не присоединяется, VM присоединяет текущий поток и затем ожидает, пока текущий поток не является единственным потоком на уровне пользователя. Java 2 SDK все еще не поддерживает разгрузку VM, как бы то ни было. DestroyJavaVM всегда возвращает код ошибки. jint GetEnv(JavaVM *vm, void **env, jint version);
*env к NULL, и возвраты JNI_EDETACHED. Если указанная версия не поддерживается, наборы *env к NULL, и возвраты JNI_EVERSION. Иначе, наборы *env к соответствующему интерфейсу, и возвратам JNI_OK.