0

在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同一类的引用可能不同。

有没有优化的解决方案?

4

2 回答 2

0

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

jclass globalRefCls = jni->NewGlobalRef(localRefCls);

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

更新

在评论中的谈话之后,我重新阅读了您的要求。
只要你每次都得到一个jobject,你无论如何都需要把jclass拿出来,你的map也可以是map,其中字符串是类的描述符。

每次你得到一个作业时,提取 jclass 并询问它的名字(你可以缓存 java/lang/Class getName 方法)。

您还可以根据需要在前面创建此缓存,因为您知道要期望哪些对象(实现 I 的对象)

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

于 2013-02-08T14:07:14.600 回答
0

我能想到的解决方案之一是通过将类A, B, C, ...jclass引用缓存到任何数据结构(数组、列表等;map 在这里没有加速)。我们称这个结构为 Storage。然后我可以优化步骤(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()很快,那么这会进行优化。

于 2013-02-08T16:09:04.540 回答