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) から始めて、 cached を使用することもできmap <jclass, jmethodID>ます。ただし、jclass同じクラスでも参照が異なる可能性があるため、これもおそらく機能しません。

最適化ソリューションはありますか?

4

2 に答える 2

0

私が考えることができる解決策の 1 つは、任意のデータ構造 (配列、リスト、何でも; マップはここでは高速化されません) へA, B, C, ...の参照によってクラスをキャッシュすることです。jclassこの構造をストレージと呼びましょう。次に、ステップ (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 に答える
0

プログラムの性質と「インターフェイス I」を実装するクラスの数、および使用可能なクラス ローダーの数 (クラスの数を増やすことができる) に応じて、それらのクラスへのグローバル参照を作成することを決定できます。

jclass globalRefCls = jni->NewGlobalRef(localRefCls);

次に、それらのインスタンスと jmethodID をマップにキャッシュして、後で使用できるようにします。

アップデート

コメントで話した後、私はあなたの要件を読み直しました。毎回ジョブジェクトを取得する限り、とにかく
jclass を取得する必要があります。マップは、文字列がクラスの記述子であるマップにすることもできます。

jobject を取得するたびに、jclass を抽出し、その名前を尋ねます (java/lang/Class の getName メソッドをキャッシュできます)。

どのオブジェクトが期待されるかを知っているので、必要に応じてこのキャッシュを事前に作成することもできます (I を実装するオブジェクト)。

そうは言っても、IsSameObject をチェックするほど効率的ではないと思います。

于 2013-02-08T14:07:14.600 に答える