NDK学習のJNIの中でObjectのいくつかの列の操作について

6287 ワード

今日はJNIでObjectの操作を学びました.javaを使用すると、親参照がサブクラスオブジェクトを指し、このオブジェクト参照を取得することでいくつかの列の操作を行うことができます.JNIでは、Objectを作成していくつかのカラムを操作することもできます.その前にいくつかの概念JNIEnv、jobjectを導入する必要があります.後でこの2つのタイプを頻繁に使用するからです.
  • JNIEnv:javaとC/C++の間の翻訳者として理解できる構造体を指します.
  • jobject:nativeメソッドがstaticでない場合、このobjはこのnativeメソッドのクラスインスタンスを表し、nativeメソッドがstaticである場合、このobjはこのnativeメソッドのクラスのclassオブジェクトインスタンスを表す.

  • この2つのタイプを理解してから、私たちは本当の本の勉強を始めました.JNIのObjectに対する操作です.
    まず、割り当てによってオブジェクトを取得する方法について説明します.レプリケーションとしても理解できます.例に従ってTestクラスを作成する
    public class Test { 
      public void temp() {
          Log.e("TAG", "  text   temp  ");
      }
    }
    

    その後、MainActivityでnativeメソッドを作成します.
    public class MainActivity extends AppCompatActivity {
    Test test = new Test();
    
    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        // Example of a call to a native method
        TextView tv = (TextView) findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
         testObject(test);//  native  
    }
    
    public native String stringFromJNI();
    
    public native void testObject(Test test);
    }
    

    testObjectの赤字でnative-lib.cppファイル生成nativeメソッド
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_captain_wudongsheng_day3ndk_MainActivity_testObject(JNIEnv  *env,  /*native  class  ,      MainActivity*/ jobject instance,
                                                           /*     */  jobject test) {
      /*     java */
      jclass testclass = env->FindClass("com/captain/wudongsheng/day3ndk/Test");//         Test ,                
      jobject testobject = env->AllocObject(testclass);
    
      /*jmethodID GetMethodID(jclass clazz /* */, const char* name/*   */, const char* sig/*    */)*/
      jmethodID temmid = env->GetMethodID(testclass, "temp", "()V");//    methodID
      env->CallVoidMethod(testobject, temmid);//  Call  
    
    }
    

    実行後、コンソールでログ出力をスムーズに見ることができ、temp()メソッドを実行しました.
    10-30 16:53:00.501 2524-2524/com.captain.wudongsheng.day3ndk E/TAG:   text   temp  
    

    Local Reference(ローカルリファレンス)が使用されなくなった場合、void DeleteLocalRef(jobject localRef)を呼び出すのが望ましい.これは、Local Referenceが作成されすぎてout of memoryになるためである.実際、nativeMethodは、常に1つしか見えないのではなく、実行中により多くのJNI Local Referenceを作成しています.多すぎるLocal Referenceは、JNI内部のJNI Local Referenceテーブルのメモリオーバーフローを招き、興味のある学生はforループしてみてください.
    Javaオブジェクトを作成する方法もあります.NewObjec(jclass clazz,jmethodID methodID,...)ここで2番目のパラメータはコンストラクション関数名IDであり、固定された書き方は、3番目のパラメータメソッドのパラメータリストである.
     /*    java  */
    jmethodID testmid = env->GetMethodID(testclass,/*             */"","(I)V");
    jobject newobject = env->NewObject(testclass, /*     ID*/testmid);
    

    上記の2つの方法で取得したオブジェクトのタイプは、JNI 1.6で導入した方法jobjectRefType GetObjectRefType(jobjectobj)でオブジェクト参照のタイプを取得できます.
     /*  obj          */
    jobjectRefType allcotype = env->GetObjectRefType(allocobject);
    jobjectRefType newtype = env->GetObjectRefType(newobject);
    LOGE("allcotype=%d newtype=%d",allcotype,newtype);
    

    ではjobjectRefTypeは何なのか、jniに入ります.hヘッダファイルには、列挙が定義されていることがわかります.
    typedef enum jobjectRefType {
      JNIInvalidRefType = 0//obj           
      JNILocalRefType = 1,//obj         
      JNIGlobalRefType = 2, //obj         
      JNIWeakGlobalRefType = 3. //obj          
    } jobjectRefType;
    

    ログ印刷では、ローカルリファレンスであることもわかります
      10-30 17:53:16.316 3316-3316/com.captain.wudongsheng.day3ndk E/JNI: (/Users/wudongsheng/Downloads/Day3NDK/app/src/main/cpp/native-lib.cpp:78) void Java_com_captain_wudongsheng_day3ndk_MainActivity_testObject(JNIEnv *, jobject, jobject): allcotype=1 newtype=1
    

    次に、Objectがclazzオブジェクトに強く移行できるかどうかを学習します.この場合、jboolean IsInstanceOf(jobject obj,jclass clazz)メソッドが必要です.戻り値はjbooleanです.
    jboolean allj = env->IsInstanceOf(allocobject, testclass);
    jboolean newJ = env->IsInstanceOf(newobject, testclass);
    
    jboolean allj1 = env->IsInstanceOf(allocobject, clazz);//clazz     native        
    jboolean newJ1 = env->IsInstanceOf(newobject, clazz);
    //PS:       NULL,       class  ,
    LOGE("%d %d %d %d",allj,newJ,allj1,newJ1);
    

    logログの表示:出力は1 1 0 0で、あなたがコピーしたオブジェクトとnewから出てきたオブジェクトは間違いなく入ってきたオブジェクトとは違います.
    10-30 17:53:16.316 3316-3316/com.captain.wudongsheng.day3ndk E/JNI: (/Users/wudongsheng/Downloads/Day3NDK/app/src/main/cpp/native-lib.cpp:96) void Java_com_captain_wudongsheng_day3ndk_MainActivity_testObject(JNIEnv *, jobject, jobject): 1 1 0 0
    

    最後に、2つの参照が同じjavaオブジェクトjboolean IsSameObject(jobject ref 1,jobject ref 2)を参照しているかどうかを確認する知識点があります.
    jfieldID jtestID = env->GetFieldID(clazz, "test", "Lcom/captain/wudongsheng/day3ndk/Test;");//  fieldID
    jobject testJobject = env->GetObjectField(instance, jtestID);//  ObjectField
    //test        testJobject  ID     
    jboolean jsameObject1 = env->IsSameObject(test, testJobject);//
    jboolean jsameObject2 = env->IsSameObject(test, allocobject);//    
    jboolean jsameObject3 = env->IsSameObject(test, newobject);//     
    jboolean jsameObject4 = env->IsSameObject(allocobject, testJobject);
    jboolean jsameObject5 = env->IsSameObject(allocobject, newobject);
    jboolean jsameObject6 =  env->IsSameObject(testJobject, newobject);
    
    LOGE("%d %d %d %d %d %d",jsameObject1,jsameObject2,jsameObject3,jsameObject4,jsameObject5,jsameObject6);
    

    最後のログ出力の結果は次のとおりです.
    10-30 17:53:16.316 3316-3316/com.captain.wudongsheng.day3ndk E/JNI: (/Users/wudongsheng/Downloads/Day3NDK/app/src/main/cpp/native-lib.cpp:110) void Java_com_captain_wudongsheng_day3ndk_MainActivity_testObject(JNIEnv *, jobject, jobject): 1 0 0 0 0 0
    

    最初は同じjavaオブジェクトのみであり、testはMainActivityから渡され、testJobjectはGetObjectFieldによってMainActivityから取得され、明らかに同じオブジェクトであることがわかります.最後に2つの方法が追加されました.
  • jfieldID GetFieldID(jclass clazz, const char* name, const char* sig)
  • jobject GetObjectField(jobject obj, jfieldID fieldID)

  • これも次のブログで勉強する内容ですが、今日はこのブログがここまでです.
    NDK開発入門から――?