Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/367.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JNI:给定jobject,获取其缓存方法_Java_C++_Caching_Optimization_Java Native Interface - Fatal编程技术网

Java JNI:给定jobject,获取其缓存方法

Java JNI:给定jobject,获取其缓存方法,java,c++,caching,optimization,java-native-interface,Java,C++,Caching,Optimization,Java Native Interface,在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 目的是打电话

在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
引用可能不同


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

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

jclass globalRefCls = jni->NewGlobalRef(localRefCls);
然后,您可以将这些实例和jmethodID缓存在映射中以供以后使用

更新

在评论中发言后,我重新阅读了您的要求。
只要每次都得到一个jobject,就需要将jclass导出,映射也可以是映射,其中字符串是类的描述符

每次获得jobject时,提取jclass并请求它的名称(可以缓存java/lang/Class getName方法)

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


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

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

Chen,如果您建议通过类的
jclass
引用缓存类
A、B、C…
,那么它就不会起作用,正如我在问题末尾所写的那样。在映射中缓存任何引用(本地或全局)都是不好的,因为对同一Java类/对象的不同引用的值可能不同!为什么您认为缓存对类的全局引用可能有所不同?您是否使用可以卸载类的VM?或者通过不同的类加载器加载多个类的VM?请阅读的“本地和全局引用”部分下以“所有JNI方法接受…”开头的两段。这不适用于jclass,因为如果不使用不同的类加载器,就无法创建相同类型的两个类对象。恐怕这适用于类。我刚做了一个测试。我调用了
jclass c0=jenv->GetObjectClass(jobj)然后,我进行了100次调用
jclass c1=jenv->GetObjectClass(jobj)比较(c0==c1)给出false(可能,对于所有100种情况),而IsSameObject(c0,c1)给出true。这个测试是在一个本机函数中完成的,就在它启动之后,作为一个代码块。