【问题标题】:JNI GetObjectClass with primitive type具有原始类型的 JNI GetObjectClass
【发布时间】:2020-06-03 16:31:14
【问题描述】:

我有以下 JNI/JVMTI 代码:

jfieldID field = ...;
jobject fieldValue = (*jni_env)->GetObjectField(jni_env, jObjectInstance, field);
jclass fieldClass = (*jni_env)->GetObjectClass(jni_env, fieldValue);
char* signature_ptr;
char* generic_ptr;
(*jvmti_env)->GetClassSignature(jvmti_env, fieldClass, &signature_ptr, &generic_ptr);

只要 field 是引用类型(java.lang.Object 和子类型),此代码就可以工作。如果 field 是原始类型,它会在尝试执行 GetObjectClass 时使 JVM 崩溃。

我的问题是:如何使用 fieldfieldValue 来确定它是否是原始类型以及是否是原始类型,哪个(int,long ,布尔值等)?

我是 JNI/JVMTI 的新手,所以如果答案很明显,请多多包涵。

谢谢!

【问题讨论】:

  • 您是如何获得jfieldID field的? JNIGetFieldID函数需要字段名和签名,所以通常在获取jfieldID时,你已经知道了字段的类型。
  • JVMTI GetClassFields 中有一个方法可以返回一个 jclass 的所有字段。

标签: java jvm java-native-interface jvmti


【解决方案1】:

使用不是对象类型的jfieldID 调用GetObjectField 是非法的。对于原始字段,您需要调用其他Get[Type]Field 函数之一,其中[Type]Int/Long/Boolean/等。

既然你已经有了jvmti_env,那么找到jfieldID类型最简单的方法就是调用JVM TI的GetFieldName函数。除其他外,它返回字段签名,即字段的类型。

唯一的问题是jfieldID 应该始终伴随jclass - 字段的持有者,因为字段ID 是相对于特定类的。通常,当您获得jfieldID 时,您已经知道它的持有者类。如果不是,在您的情况下,您有 jObjectInstance - 一个具有此字段的对象,因此可以使用 JNI GetObjectClass 函数从实例派生持有者类。

jclass fieldHolder = (*jni_env)->GetObjectClass(jni_env, jObjectInstance);

char* name;
char* signature;
if ((*jvmti_env)->GetFieldName(jvmti_env, fieldHolder, field, &name, &signature, NULL) == 0) {

    switch (signature[0]) {
        case 'I':
            // int
            break;
        case 'J':
            // long
            break;
        ...
        case 'L':
            // object
            break;
        case '[':
            // array
            break;
    }

    (*jvmti_env)->Deallocate(jvmti_env, signature);
    (*jvmti_env)->Deallocate(jvmti_env, name);
}

【讨论】:

  • 谢谢!我看到并尝试使用 GetFieldName,但我误解了 jclass 参数的文档,它说 要查询的字段的类。我以为是 jfieldID 的类,而不是保存该字段的实例的类。
猜你喜欢
  • 2011-01-30
  • 2013-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-05
  • 2018-07-13
  • 2010-12-11
相关资源
最近更新 更多