JNI:给定jobject,获取它的缓存方法

JNI: Given jobject, obtain its cached method

本文关键字:缓存 方法 获取 给定 jobject JNI      更新时间:2023-10-16

在Java中,我有一个接口:

public interface I {...}

声明一个函数void f(),以及一些类:

public class A implements I {...}
public class B implements I {...}
public class C implements I {...}
...

我经常调用本机函数:

public native void nativeFunc(I obj);

在C++中,我获得了

jobject jobj

目的是调用

jobj.f();

而不是每次都通过链

cls = jenv->GetObjectClass(jobj);           (1)
mid = jenv->GetMethodID(cls, "f", "()V");   (2)
jenv->CallVoidMethod(jobj, mid);            (3)

我似乎无法在本机调用之间缓存mid。作为另一个建议,我可以从第(1)行开始,然后使用缓存的map <jclass, jmethodID>。然而,这可能也不起作用,因为jclass引用对于同一个类可能不同。

是否有任何优化解决方案?

我能想到的解决方案之一是通过jclass引用将类A, B, C, ...缓存到任何数据结构中(数组、列表等等;映射在这里没有加速)。让我们把这种结构称为存储。然后我可以优化步骤(2),并具有以下链:

(1) ... (obtain jcls)
(2) for(jclass jclsStored : Storage) {
        if(IsSameObject(jcls, jclsStored))
        {
            mid = ...;
            classFound = true;
        }
    }
    if(!classFound)
        Storage.add(necessary info);
(3) ...            

即,我使用JNI

IsSameObject()

函数来绕过同一类的不同jclass值。如果IsSameObject()很快,那么这就进行了优化。

根据程序的性质和实现"接口I"的类的数量,以及可用的类加载器的数量(可以乘以类的数量),您可以决定创建对这些类的全局引用

jclass globalRefCls = jni->NewGlobalRef(localRefCls);

然后,您可以将这些实例和jmethodID缓存在映射中以供以后使用。

更新

在谈话结束后的评论中,我重读了你的要求
只要你每次都得到一个jobject,你就需要得到jclass,你的映射也可以是map,其中字符串是类的描述符。

每次获得jobject时,提取jclass并询问其名称(可以缓存java/lang/Class getName方法)。

您也可以根据自己的意愿提前创建这个缓存,因为您知道需要哪些对象(实现I的对象)

话虽如此,我想它不会像检查IsSameObject那样高效。