没有可遵循的内置方法,但是这里有一些标准,简洁和可重复的实现,显示了我如何实践IBM的建议。
我假设您正在从Java调用DLL,并且在整个应用程序生命周期中多次引用它。
命名示例Native Java Class
org.stackoverflow.jni.NativeClazz,它将实现2个内置JNI方法
JNI_onLoad()和
JNI_onUnload()。
void JNI_OnLoad(JavaVM * vm,void * reserved):
此方法将用于将类ID注册为全局变量,并将方法ID和字段ID分配给静态变量。当Java VM加载驱动程序时,将自动调用该方法。在驱动程序生命周期中仅调用一次。
void JNI_OnUnload(JavaVM * vm,void * reserved):
此方法将用于释放由注册的所有全局变量
JNI_onLoad()。VM将
JNI_onUnload()在应用程序关闭之前立即自动调用。
原理: 我的理解是必须将类ID注册为全局引用,以维护任何关联的方法ID
/字段ID的可行性。如果不这样做,并且从JVM卸载了类,则在重新加载类时,方法ID
/字段ID可能会不同。如果将类ID注册为全局引用,则不需要将关联的方法ID和字段ID注册为全局引用。将类ID注册为全局引用可以防止关联的Java类卸载,因此可以稳定方法ID
/字段ID的值。包括类ID在内的全局引用应在中删除
JNI_onUnload()。
方法ID和字段ID不受本机代码管理;它们由虚拟机管理,并且在卸载相关的类之前一直有效。在虚拟机卸载定义类之前,无法显式删除字段ID和方法ID。卸载后,它们可以留给VM处理。
样例代码
以下C ++代码部分中的注释说明了全局注册变量。
这是BeanObject
表示数据对象的Java类:
package org.stackoverflow.data;public class BeanObject { String foo = ""; public String getFoo() { return foo; }}这是一个基本的Java类NativeClazz
:
package org.stackoverflow.jni;import org.stackoverflow.data.BeanObject;public class NativeClazz { // Static area for forced initialization static { // Load Native Library (C++); calls JNI_onLoad() System.loadLibrary("Native_Library_File_Name"); } public static native void staticNativeMethod(BeanObject bean); public native void instanceNativeMethod(BeanObject bean);}这是使用javah
on 生成的C ++头文件NativeClazz
:
#include <jni.h>#ifndef _Included_org_stackoverflow_jni_NativeClazz#define _Included_org_stackoverflow_jni_NativeClazz#ifdef __cplusplusextern "C" {#endifJNIEXPORT void JNICALL Java_org_stackoverflow_jni_NativeClazz_staticNativeMethod (JNIEnv *, jclass, jobject);JNIEXPORT void JNICALL Java_org_stackoverflow_jni_NativeClazz_instanceNativeMethod (JNIEnv *, jobject, jobject);#ifdef __cplusplus}#endif#endif这是实现头文件的C ++ .cpp文件:
#include "org_stackoverflow_jni_NativeClazz.h"using namespace std;static jclass JC_BeanObject;static jmethodID JMID_BeanObject_getFoo;static jint JNI_VERSION = JNI_VERSION_1_8;jint JNI_onLoad(JavaVM* vm, void* reserved) { // Obtain the JNIEnv from the VM and confirm JNI_VERSION JNIEnv* env; if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION) != JNI_OK) { return JNI_ERR; } // Temporary local reference holder jclass tempLocalClassRef; // STEP 1/3 : Load the class id tempLocalClassRef = env->FindClass("org/stackoverflow/data/BeanObject"); // STEP 2/3 : Assign the ClassId as a Global Reference JC_BeanObject = (jclass) env->NewGlobalRef(tempLocalClassRef); // STEP 3/3 : Delete the no longer needed local reference env->DeleteLocalRef(tempLocalClassRef); // Load the method id JMID_BeanObject_getFoo = env->GetMethodID(JC_BeanObject, "getFoo", "(Ljava/lang/String;)V"); // ... repeat prior line for any other methods of BeanObject // ... repeat STEPS 1-3 for any other classes; re-use tempLocalClassRef. // Return the JNI Version as required by method return JNI_VERSION;}void JNI_onUnload(JavaVM *vm, void *reserved) { // Obtain the JNIEnv from the VM // NOTE: some re-do the JNI Version check here, but I find that redundant JNIEnv* env; vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION); // Destroy the global references env->DeleteGlobalRef(JC_BeanObject); // ... repeat for any other global references}JNIEXPORT void JNICALL Java_org_stackoverflow_jni_NativeClazz_staticNativeMethod (JNIEnv * env, jclass clazz, jobject jBeanObject) { // Retrieve jstring from the Java Object jstring jFoo = (jstring)env->CallObjectMethod(jBeanObject, JMID_BeanObject_getFoo); // Make accessible to C++ const char * cFoo = env->GetStringUTFChars(jFoo, NULL); // Do something with cFoo... // Release Resources env->ReleaseStringUTFChars(jFoo, cFoo); env->DeleteLocalRef(jFoo);}JNIEXPORT void JNICALL Java_org_stackoverflow_jni_NativeClazz_instanceNativeMethod (JNIEnv * env, jobject selfReference, jobject jBeanObject) { // Retrieve jstring from the Java Object jstring jFoo = (jstring)env->CallObjectMethod(jBeanObject, JMID_BeanObject_getFoo); // Make accessible to C++ const char * cFoo = env->GetStringUTFChars(jFoo, NULL); // Do something with cFoo... // Release Resources env->ReleaseStringUTFChars(jFoo, cFoo); env->DeleteLocalRef(jFoo);}


