1

説明

JNIXMLDocumentいくつかのJAVAメソッド呼び出しを行った私のC++アプリケーションクラス。クラスのコンストラクターで、JNIXMLDocument現在のスレッドをアタッチしてクラスメンバーに設定しJNIEnv* m_JavaEnv、すべてのメソッドで使用します。また、コンストラクターで、JAVAクラスを見つけてクラスメンバーに設定し、クラスからそのクラスオブジェクトを取得して、com/fido/android/framework/service/XMLDOMDocumentクラスメンバーに設定しようとしています。m_XMLDocumentClassm_XMLDocumentObject

C++コード

class JNIXMLDocument
{
    /* Constructor **/
    JNIXMLDocument()
    {
        /* Get JNI right version and set it. **/
        jint interface_id = JNI_VERSION_1_2;
        #ifdef JNI_VERSION_1_2
            interface_id = JNI_VERSION_1_2;
        #else
            interface_id = JNI_VERSION_1_1;
        #endif

        /* Trying to attach current thread. **/
        int res = g_JavaVirtualMachine->GetEnv(&m_JavaEnv, interface_id);
        if (res == JNI_EDETACHED || res == JNI_EVERSION) {
            res = g_JavaVirtualMachine->AttachCurrentThread(&m_JavaEnv, NULL);
        }

        /* Get Class from Java **/
        m_XMLDocumentClass = m_JavaEnv->FindClass("com/fido/android/framework/service/XMLDOMDocument");
        if (m_XMLDocumentClass != NULL) {
            /* Call java class constructor. **/
            jmethodID constructor = m_JavaEnv->GetMethodID(m_XMLDocumentClass , "<init>", "()V");
            m_XMLDocumentObject = m_JavaEnv->NewObject(m_XMLDocumentClass , constructor);    

        }

    }

    bool Initialize()
    {
        jmethodID method = m_JavaEnv->GetMethodID(m_XMLDocumentClass, "Initialize", "()Lorg/w3c/dom/Document;");
        jobject document = m_JavaEnv->CallObjectMethod(m_XMLDocumentObject , method);

    }

    private:
        JNIEnv* m_JavaEnv;
        jclass  m_XMLDocumentClass;
        jobject m_XMLDocumentObject;


};

C ++コード(正しい方法)

class JNIXMLDocument
{
    /* Constructor **/
    JNIXMLDocument()
    {
        /* Get JNI right version and set it. **/
        jint interface_id = JNI_VERSION_1_2;
        #ifdef JNI_VERSION_1_2
            interface_id = JNI_VERSION_1_2;
        #else
            interface_id = JNI_VERSION_1_1;
        #endif

        JNIEnv* env;
        /* Trying to attach current thread. **/
        int res = g_JavaVirtualMachine->GetEnv(&env, interface_id);
        if (res == JNI_EDETACHED || res == JNI_EVERSION) {
            res = g_JavaVirtualMachine->AttachCurrentThread(&env, NULL);
        }

        /* Get Class from Java **/
        jclass localClass = env->FindClass("com/fido/android/framework/service/XMLDOMDocument");
        if (localClass != NULL) {
            m_XMLDocumentClass = env->NewGlobalRef(localClass);
            /* Call java class constructor. **/
            jmethodID constructor = env->GetMethodID(localClass, "<init>", "()V");
            jobject localObject = env->NewObject(m_XMLDocumentClass , constructor);    
            m_XMLDocumentObject = env->NewGlobalRef(localObject );
        }

    }

    bool Initialize()
    {

    }

    private:
        jclass  m_XMLDocumentClass;
        jobject m_XMLDocumentObject;


};

質問

  1. JNIEnv* m_JavaEnvコンストラクターでJNIインターフェイスポインター()を一度設定して、コード全体で使用するのは正しいですか?
  2. jclass m_XMLDocumentClassコンストラクターで設定し、その変数をすべてのメソッドで使用するのは正しいですか?
  3. jobject m_XMLDocumentObjectこの方法でコンストラクターを設定するのは正しいですm_JavaEnv->NewObject(m_XMLDocumentClass , constructor);か、それとも私はを呼び出さなければなりませんNewGlobalRef
  4. アプリケーションが同じスレッドで動作しない場合(多くのスレッドを使用する場合)、どのような問題が発生する可能性がありますか?
4

1 に答える 1

3

コンストラクターでJNIインターフェースポインター(JNIEnv * m_JavaEnv)を一度設定して、コード全体で使用するのは正しいですか?

いいえ。スレッド固有です。それがAttach/DetachCurrentThreadの目的です。これが機能する唯一の方法は、C++オブジェクトが同じスレッドで構築および破棄された場合です。

コンストラクターでjclassm_XMLDocumentClassを設定し、その変数をすべてのメソッドで使用するのは正しいですか?

いいえ。これはローカル参照であり、取得したJNIメソッドが返されると期限切れになります。単一のJNIメソッド内でのみ使用される場合を除き、グローバル参照または弱参照として保存する必要があります。

Is it right to set jobject m_XMLDocumentObject in the constructor in this way m_JavaEnv->NewObject(m_XMLDocumentClass , constructor);

いいえ:上記を参照してください。

または多分私はNewGlobalRefを呼び出さなければなりません。

はい、上記のとおりです。

アプリケーションが同じスレッドで動作しない場合(多くのスレッドを使用する場合)、どのような問題が発生する可能性がありますか?

主にJVMがクラッシュします。JVMは、JNI仕様のすべてのルールに従うことを前提としています。そうしてください。

于 2012-06-12T08:39:58.893 に答える