问题描述
我在上阅读
如何一个缓存 methodID
, fieldID
和 class
JNI中的对象?
是否有必须遵循的内置方法或特定程序?
How does one cache the methodID
, fieldID
, and class
objects in JNI?Are there built-in methods or a specific procedure that has to be followed?
推荐答案
没有内置方法在接下来的方法中,不过这里有一个标准的,干净的,可重复的实现,展示了我如何实践IBM的建议。
There is no built-in methodology to follow, however here is a somewhat standard, clean, and repeatable implementation showing how I practice IBM's recommendation.
我将假设你正在调用你的DLL Java和您在整个应用程序生命周期中多次引用它。
I am going to assume you are calling your DLL from Java and you are referencing it multiple times throughout your application life-cycle.
示例Native Java Class名为 org.stackoverflow.jni.NativeClazz
,它将实现2个内置JNI方法 JNI_OnLoad()
和 JNI_OnUnload()
。
The sample Native Java Class is named org.stackoverflow.jni.NativeClazz
, which will implement the 2 built-in JNI methods JNI_OnLoad()
and JNI_OnUnload()
.
void JNI_OnLoad(JavaVM * vm,void * reserved):此方法将用于将类ID注册为全局变量和将方法ID和字段ID分配给静态变量。当Java VM加载驱动程序时,将自动调用该方法;它只在驱动程序生命周期中调用一次。
void JNI_OnLoad(JavaVM *vm, void *reserved): This method will be used to register the Class IDs as global variables and assign the Method IDs and Field IDs to static variables. The method is automatically called when the driver is loaded by the Java VM; it is only called once during the driver life-cycle.
void JNI_OnUnload(JavaVM * vm,void * reserved):此方法将是用于释放由 JNI_OnLoad()
注册的任何全局变量。在应用程序关闭之前,VM会立即自动调用 JNI_OnUnload()
。
void JNI_OnUnload(JavaVM *vm, void *reserved): This method will be used to free any global variables registered by JNI_OnLoad()
. The VM will automatically call JNI_OnUnload()
immediately prior to application shutdown.
理由:我的理解是必须将类ID注册为全局引用,以维护任何关联的方法ID /字段ID的可行性。如果未执行此操作并且从JVM卸载类,则在类重新加载时,方法ID /字段ID可能不同。如果将类ID注册为全局引用,则不需要将关联的方法ID和字段ID注册为全局引用。将类ID注册为全局引用可防止关联的Java类卸载,从而稳定方法ID /字段ID值。全局引用,包括类ID,应该在 JNI_OnUnload()
中删除。
Rationale: It's my understanding the Class IDs must be registered as global references to maintain the viability of any associated Method ID / Field IDs. If this isn't done and the class is unloaded from the JVM, on class reload, the Method IDs / Field IDs may be different. If the Class ID is registered as a global reference, the associated Method IDs and Field IDs do not need to be registered as global references. Registering a Class ID as a global reference prevents the associated Java class from unloading, therefore stabilizing the Method ID / Field ID values. Global references, including the Class ID,s should be removed in JNI_OnUnload()
.
方法ID和字段ID不受本机代码管理;它们由虚拟机管理,并且在卸载关联类之前一直有效。在虚拟机卸载定义类之前,无法显式删除字段ID和方法ID;它们可以在卸载后留给VM处理。
Method IDs and Field IDs are not managed by the native code; they are managed by the virtual machine and are valid until the associated class is unloaded. Field IDs and Method IDs cannot be explicitly deleted before the virtual machine unloads the defining class; they can be left for the VM to handle after unload.
示例代码
以下C ++代码部分中的注释解释了全局注册变量。
Comments in the following C++ code sections explain registering variables globally.
这是Java类 BeanObject
表示数据对象:
Here is the Java class BeanObject
representing a data object:
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");
}
/**
* A static native method you plan to call.
*/
public static native void staticNativeMethod(BeanObject bean);
/**
* A non-static native method you plan to call, to show this also works with
* instantiated Java classes.
*/
public native void instanceNativeMethod(BeanObject bean);
}
这是使用 javah on NativeClazz
:
Here is the C++ header file generated using javah
on NativeClazz
:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_stackoverflow_jni_NativeClazz */
#ifndef _Included_org_stackoverflow_jni_NativeClazz
#define _Included_org_stackoverflow_jni_NativeClazz
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_stackoverflow_jni_NativeClazz_staticNativeMethod
* Method: staticNativeMethod
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_stackoverflow_jni_NativeClazz_staticNativeMethod
(JNIEnv *, jclass, jobject);
/*
* Class: org_stackoverflow_jni_NativeClazz_instanceNativeMethod
* Method: instanceNativeMethod
* Signature: ()V
*/
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 Global Variables to cache Java Class and Method IDs
**************************************************************/
static jclass JC_BeanObject;
static jmethodID JMID_BeanObject_getFoo;
/**************************************************************
* Declare JNI_VERSION for use in JNI_Onload/JNI_OnUnLoad
* Change value if a Java upgrade requires it (prior: JNI_VERSION_1_6)
**************************************************************/
static jint JNI_VERSION = JNI_VERSION_1_8;
/**************************************************************
* Initialize the static Class and Method Id variables
**************************************************************/
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;
}
/**************************************************************
* Destroy the global static Class Id variables
**************************************************************/
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
}
/**************************************************************
* A Static Native Method
**************************************************************/
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);
}
/**************************************************************
* Instance / Non-Static Native Method
**************************************************************/
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);
}
这篇关于在JNI中,如何根据IBM的性能建议缓存类,methodID和fieldID?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!