- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我在 on IBM 上阅读那个
To access Java objects' fields and invoke their methods, native code must make calls to FindClass(), GetFieldID(), GetMethodId(), and GetStaticMethodID(). In the case of GetFieldID(), GetMethodID(), and GetStaticMethodID(), the IDs returned for a given class don't change for the lifetime of the JVM process. But the call to get the field or method can require significant work in the JVM, because fields and methods might have been inherited from superclasses, making the JVM walk up the class hierarchy to find them. Because the IDs are the same for a given class, you should look them up once and then reuse them. Similarly, looking up class objects can be expensive, so they should be cached as well.
如何缓存 JNI 中的methodID
、fieldID
和class
对象?是否有必须遵循的内置方法或特定程序?
最佳答案
没有可遵循的内置方法,但这里有一个标准、干净且可重复的实现,展示了我如何实践 IBM 的建议。
我将假设您从 Java 调用 DLL,并且在整个应用程序生命周期中多次引用它。
示例 Native Java 类名为 org.stackoverflow.jni.NativeClazz
,它将实现 2 个内置 JNI 方法 JNI_OnLoad()
和 JNI_OnUnload ()
.
void JNI_OnLoad(JavaVM *vm, void *reserved)
:该方法将用于将Class IDs注册为全局变量,并将Method IDs和Field IDs分配给静态变量。该方法在Java VM加载驱动时自动调用;它在驱动程序生命周期中只被调用一次。
void JNI_OnUnload(JavaVM *vm, void *reserved)
:此方法将用于释放 JNI_OnLoad()
注册的所有全局变量。 VM 将在应用程序关闭前立即自动调用 JNI_OnUnload()
。
理由:据我了解,必须将类 ID 注册为全局引用,以保持任何关联的方法 ID/字段 ID 的可行性。如果没有这样做并且类从 JVM 中卸载,则在类重新加载时,方法 ID/字段 ID 可能不同。如果 Class ID 注册为全局引用,则关联的 Method IDs 和 Field IDs 不需要注册为全局引用。将类 ID 注册为全局引用可防止卸载关联的 Java 类,从而稳定方法 ID/字段 ID 值。应在 JNI_OnUnload()
中删除全局引用,包括 Class ID。
方法 ID 和字段 ID 不由 native 代码管理;它们由虚拟机管理并且在关联类被卸载之前一直有效。在虚拟机卸载定义类之前,不能显式删除字段 ID 和方法 ID;它们可以在卸载后留给 VM 处理。
示例代码
以下 C++ 代码部分中的注释解释了全局注册变量。
这是代表数据对象的 Java 类 BeanObject
:
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
* Java class instances.
*/
public native void instanceNativeMethod(BeanObject bean);
}
这是在 NativeClazz
上使用 javah
生成的 C++ 头文件“org_stackoverflow_jni_NativeClazz.h
”: p>
/* 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; // declare for each class
static jmethodID JMID_BeanObject_getFoo; // declare for each class method
/**************************************************************
* 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);
}
关于java - 在 JNI 中,如何根据 IBM 的性能建议缓存类、方法 ID 和字段 ID?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10617735/
IBM Watson 和 IBM Inforsphere BigInsights (IBM Hadoop)/Streams 之间有什么区别? Watson 带来了 BigInsights 无法提供的哪
据我所知,Rational 是一种测试工具,而 Rational Rose 是一种建模工具。 最佳答案 Rational 是一家为软件开发生命周期制作工具的公司。 Rational Rose 就是这样
我尝试将 ibm-eventstreams-dev v 0.1.1 安装到 IBM Cloud Private 中,但收到一条错误消息: 内部服务错误:图表与 Tiller v2.6.0 不兼容 最佳
我正在尝试配置连接到集群MQ的集群Websphere应用程序服务器。 但是,我所掌握的信息是两个具有不同主机名,服务器通道和队列管理器的MQ实例的详细信息,这些主机名属于同一MQ集群名称。 在Webs
我想问问你们中的一些聪明人 :) 是否可以在 IBM Connections 文件中使用目录结构。还有图书馆,但我无法通过 webdav/smdb 映射它,也许这是关于我的信息差距,但我可以安装桌面插
我一次又一次地读到 IBM i 是一个支持多种编程语言的现代系统。除了 COBOL 和 RPG 之外,我如何确定哪些可供我使用? 维基百科上提供了一份 list ,我对 C、C++、BASIC、Sma
是否可以将 IBM HTTP 服务器设置为非 IBM Websphere 应用程序服务器(Glassfish、Apache Tomcat 或其他 Java 应用程序服务器)的前端?IBM 支持吗?我试
我有一个在 IBM Bluemix 上运行的简单 JSF 应用程序,与以下 J2EE 依赖项配合良好。 javax javaee-web-api 6.
我正在查看一个 RPG 程序。有一些这样的子程序:有没有工具哪个会将其创建为一个过程,可以在单独的过程中使用? C Eval FinQty# = 0
我正在设计一个新的体系结构大数据,我的客户将其作为IBM MQ代理使用。我们曾经在大数据架构中与Kafka一起工作,因为我想它比其他选择更快,更可靠,更强大,并且因为风暴和火花流在Kafka中更容易工
我偶然发现了一些 FMTDTA,它似乎是一种查询/排序语言,早于旧 RPG 系统中的 SQL。我试图解开它的用法。 例子: 物理文件布局: ORNO S 9 0 1
除了许可之外,IBM Worklight 的企业版和消费者版之间在功能方面是否存在任何差异? 最佳答案 企业版的销售目的是在组织内使用 (B2E)。许可证是“每台设备”。消费者版旨在以 B2C 的形式
我希望使用 IBM Worklight v5.0.5 Fix pack 1 设置 Eclipse 开发环境。 我可以获得有关旧版本 Worklight 的安装链接的一些指示吗? 最佳答案 查看下面的可
是否可以保留已检索且不再位于队列中的消息历史记录(包含消息内容将是完美的)? 在应用程序中,我可以看到发送者何时尝试将消息放入队列以及接收者何时尝试拾取消息,但我想查看消息何时真正到达队列以及消息何时
我正在向远程队列发送消息,但我无法控制该队列。 我发送一个 xml 文件作为消息,但是当应用程序读取消息时,它会得到一个消息头,例如 jms_text \0\0\0lqueue:///TEST128
在什么情况下队列管理器可能会失去与集群环境中存储库的连接?我的环境中队列管理器经常失去与存储库的连接,我需要刷新集群来修复此问题并重新建立与集群中其他队列管理器的通信。 我们的集群有 100 个队列管
我们正在为助手实现 Watson 技术,以帮助某些用户。 对话有些复杂,有时需要针对某些问题做跳答,这样做的坏处是用户可以再问一遍问题,以防不明白这就是问题所在。 当想进入后续进入的节点时,该节点进行
我们有一个启用了 DevOps 交付管道的 NodeJS Cloud Foundry 应用程序。 最初,我们将管道设置为使用 Bluemix 中交付管道的 Active Deploy 扩展来部署应用程
请注意,此问题特定于“IBM DB2 for i”,即 IBM i 操作系统的 version of DB2 . 下面的屏幕截图显示了一个故意错误的 INSERT 语句,它产生了 SQL0407 的
我想使用 IBM Websphere MQ 客户端 v7.5。我正在编写独立的 JMS 客户端应用程序来发送和使用来自 IBM WebsphereMQ 服务器的消息(它在其他地方运行,但我有权发送/接
我是一名优秀的程序员,十分优秀!