天天看點

JNI調用Java方法總結

1、首先了解一下native方法的方法簽名,方法簽名主要是描述了方法的參數和傳回值,為了防止方法的重載而導緻的調用混亂。

Java 類型 類型簽名

void V

boolean Z

byte B

char C

short S

int I

long L

float F

double D

類 L全限定名;,比如String, 其簽名為Ljava/lang/String;

數組 [類型簽名, 比如 [B

在app\build\intermediates\classes\debug的路徑下,運作javap -s yys.com.myjnidemo.JniDataUtil,就會輸出如下的方法簽名描述:

public class yys.com.myjnidemo.JniDataUtil {
  public yys.com.myjnidemo.JniDataUtil();
    descriptor: ()V

  public static native java.lang.String getStringFromJni();
    descriptor: ()Ljava/lang/String;    //括号裡面為空,表示參數為空;傳回值是String類型

  public static native java.lang.String getStringFromJni(int);
    descriptor: (I)Ljava/lang/String;  //參數是int;傳回是String類型

  public native void doSomeThings();
    descriptor: ()V   //參數為空;傳回都是void類型

  public native void doSomeThings(java.lang.String);
    descriptor: (Ljava/lang/String;)V

           

如果修改了類裡面的方法,需要重新build一下就好了。

2、jni調用java靜态方法

JNIEXPORT void JNICALL Java_yys_com_myjnidemo_JniDataUtil_doSomeThings__
    (JNIEnv * env, jobject obj){
        /**
        *找到要調用的類
        */
        jclass cls_util = env->FindClass("yys/com/myjnidemo/JniDataUtil");   //注意,這裡的使用的斜杠而不是點
        if(cls_util == NULL){
            return;
        }

        /**
        *擷取靜态方法操作的對象 ,參數分别是 jclass,方法名稱,方法簽名
        */
        jmethodID mtd_static_method = env->GetStaticMethodID(cls_util,"callStaticHandle","(Ljava/lang/String;)V");
        if(mtd_static_method == NULL){
            return;
        }

        jstring data = env->NewStringUTF("call static method");
        if(data == NULL){
            return;
        }

        /**
        *調用方法,參數是 jclass,jmethodID,傳遞的參數
        */
        env->CallStaticVoidMethod(cls_util,mtd_static_method,data);

        //删除引用
        env->DeleteLocalRef(cls_util);
        env->DeleteLocalRef(mtd_static_method);
        env->DeleteLocalRef(data);
    }
           

3、jni調用java執行個體方法

/**
            *找到要調用的類
            */
            jclass cls_util = env->FindClass("yys/com/myjnidemo/JniDataUtil");   //注意,這裡的使用的斜杠而不是點
            if(cls_util == NULL){
                return;
            }

            /**
            *擷取執行個體方法操作的對象 ,參數分别是 jclass,方法名稱,方法簽名
            */
             jmethodID mtd_method = env->GetMethodID(cls_util,"callInstanceHandle","([I)V");
               if(mtd_method == NULL){
                    return;
               }

             /**
             *擷取構造方法
             */
             jmethodID mtd_struct = env->GetMethodID(cls_util,"<init>","()V");
               if(mtd_struct == NULL){
                    return;
               }

             /**
              *擷取執行個體對象
              */
              jobject utilinstance = env->NewObject(cls_util,mtd_struct,NULL);

              jstring data = env->NewStringUTF("call instance method");
                if(data == NULL){
                     return;
               }

               /**
               *調用執行個體方法
               */
               env->CallVoidMethod(utilinstance,mtd_method,data);

                //删除引用
                env->DeleteLocalRef(cls_util);
                env->DeleteLocalRef(mtd_method);
                env->DeleteLocalRef(mtd_struct);
                env->DeleteLocalRef(utilinstance);
                env->DeleteLocalRef(data);
           

可以看出,調用執行個體方法之前,首先需要擷取類的構造方法,然後建立執行個體對象,用執行個體對象來作為參數調用執行個體方法。

繼續閱讀