牛骨文教育服务平台(让学习变的简单)
博文笔记

JNI中调用JAVA各种方法详解

创建时间:2015-03-06 投稿人: 浏览次数:1484

总结一下 C 如何 通过 JNI 层调用 Java 的静态和非静态方法

对于:JNIEXPORT void JNICALL Java_com_example_TestNative_sayHello(JNIEnv * env, jobject thiz, jstring paramString)这样一个函数 固定参数: JNIEnv *env:JNIEnv代表java环境,通过*env这个指针,就可以让我们对java层的代码进行操作,比如创建java类的对象,调用java对象的方法,获取java对象的属性等等 这个指针会被JNI传递到本地方法的实现函数中来对java端的代码进行操作。 jobject thiz:分配给这个类的类加载器 函数参数: jstring paramString:这是sayHello函数的具体参数,在外部调用的时候必须给sayHello函数一个参数,如:sayHello(“Hello JNI”); 调用java过程中(重点是调用java中的某些类的某些方法) 主要分下面几个步骤: 1.获取jclass JNIEnv类中有如下几个简单的函数可以取得jclass     jclass FindClass(const char* clsName)  根据类名来查找一个类,完整类名     jclass GetObjectClass(jobject obj)   根据一个对象,获取该对象的类     jclass GetSuperClass(jclass obj)     获取一个类的父类 FindClass:根据类名来查找,需要注意的是:这里的类名是某个类的完整路径。 如:String这个类    jclass cls_string= (*env)->FindClass(“java/lang/String”); 在用的时候 需要把 . 换成 /  2.获取类中方法的ID或类属性的ID JNI在jni.h头文件中定义了jmethodID和jfieldID类表示Java端的方法和属性 JNIEnv获取相应的jmethodID和fieldID的方法: GetMethodID/GetStaticMethodID   获取一个实例的方法ID/一个静态的方法ID GetFieldID/GetStaticMethodID         获取一个实例的域的ID/一个静态的域的ID GetMethodID原型: jmethodID (JNICALL *GetMethodID)       (JNIEnv *env, jclass clazz, const char *name, const char *sig); 第一个参数默认的*env 第二个参数是获取到的类 第三个参数是你要获取的某一个方法的名字 第四个参数是“签名”,引用这个签名的作用是对这一函数参数和返回值的描述,对于同一个函数,java是允许对它进行重载的,这时候就必须引入签名来区分他们。 3.调用方法 JNI同样提供了调用java方法的函数 JNIEnv去调用相应java方法的方法有: Call<type>Method/CallStatic<type>Method  这里的<type>是要调用的那个方法的返回值类型 大致有 CallVoidMethod                   CallStaticVoidMethod CallIntMethod                     CallStaticIntMethod CallBooleanMethod              CallStaticBooleanMethod CallByteMethod                   CallStaticByteMethod 如:(*env)->CallVoidMethod(env, obj, jm_id, parameter); 参数一默认的*env 参数二是获取到的类 参数三是要调用的方法的ID 参数四这一方法的参数 方法的签名: 形如:(参数1类型签名参数2类型签名……参数n类型签名)返回值类型签名 签名分两部分:参数 & 返回值 类型的表述方式有如下对应关系:
12345678910111213类型           相应的签名 boolean        Z byte           B char           C short          S int            I long           J float          F double         D void           V object         L用/分隔包的完整类名:   Ljava/lang/String;Array          [签名          [I      [Ljava/lang/Object; Method         (参数1类型签名 参数2类型签名···)返回值类型签名

 

注:1.object类型的每一个参数最后都得加上”;“2.方法参数或者返回值为java中的对象时,签名中必须以“L”加上其路径,不过此路径必须以“/”分开,自定义的对象也使用本规则例如说 java.lang.String为“java/lang/String”,com.nedu.jni.helloword.Student为”Lcom /nedu/jni/helloword/Student;”3.方法参数或者返回值为数组类型时,请前加上[例如[I表示 int[],[[[D表示 double[][][],即几维数组就加几个[实例:C
1 2 3 4 5 6 void f1()                         ()V int f2(int, long)                 (IJ)I boolean f3(int[])                 ([I)B double f4(String, int)            (Ljava/lang/String;I)D void f5(int, String [], char)    (I[Ljava/lang/String;C)V byte[] f6(int, String, String)   (ILjava/lang/String;Ljava/lang/String)[B
下面以几个实例来重点介绍下方法的签名的书写方式 a、调用某一个类的构造函数: Java
12345678SecureRandom localSecureRandom = new SecureRandom();//获取类:jclass jc_SecureRandom = (*env)->FindClass(env, "java/security/SecureRandom");//获取构造函数的ID,构造函数的名称都是“<init>”;//签名:形如"()V"  括号里是参数类型,括号外是返回值类型,这里无参数,返回值是VoidjmethodID jm_constructor = (*env)->GetMethodID(env, jc_SecureRandom, "<init>", "()V");//调用:jobject jo_SecureRandom = (*env)->NewObject(env, jc_SecureRandom, jm_constructor);

 

b、调用String类的getBytes方法:Java
1 2 3 4 5 6 7 8 9 //获取类: jclass jc_string = (*env)->FindClass(env, "java/lang/String"); //获取方法ID: jmethodID jm_getBytes =     (*env)->GetMethodID(env, jc_string, "getBytes", "()[B"); //参数为空,返回值为byte[] //调用: jbyteArray jb_paramString =     (jbyteArray)(*env)->CallObjectMethod(env, paramString, jm_getBytes);

 

c、调用Cipher类的getInstance方法:
1234567891011//获取类:jclass jc_Cipher = (*env)->FindClass(env, "javax/crypto/Cipher");//获取方法ID:jmethodID jm_Cipher_getInstance =     (*env)->GetStaticMethodID(env, jc_Cipher, "getInstance",    "(Ljava/lang/String;)Ljavax/crypto/Cipher;");  //参数是一个string, 返回值是一个Cipher//调用:jobject jo_Cipher =     (*env)->CallStaticObjectMethod(env, jc_Cipher, jm_Cipher_getInstance,                                (*env)->NewStringUTF(env, "DES"));

 

实例一:

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 /* c/c++ string turn to java jstring */ jstring charToJstring(JNIEnv* env, const char* pat) {     jclass strClass = (*env)->FindClass(env, "java/lang/String");     jmethodID  ctorID =          (*env)->GetMethodID(env, strClass, "<init>",                               "([BLjava/lang/String;)V");     jbyteArray bytes = (*env)->NewByteArray(env, strlen(pat));     (*env)->SetByteArrayRegion(env, bytes, 0, strlen(pat), (jbyte*)pat);     jstring encoding = (*env)->NewStringUTF(env, "UTF-8");     return (jstring)                (*env)->NewObject(env, strClass, ctorID, bytes, encoding); }   /* java jstring turn to c/c++ char* */ char* jstringToChar(JNIEnv* env, jstring jstr) {     char* pStr = NULL;     jclass jstrObj = (*env)->FindClass(env, "java/lang/String");     jstring encode = (*env)->NewStringUTF(env, "utf-8");     jmethodID methodId  =         (*env)->GetMethodID(env, jstrObj, "getBytes",                                       "(Ljava/lang/String;)[B");     jbyteArray byteArray = (jbyteArray)         (*env)->CallObjectMethod(env, jstr, methodId, encode);     jsize strLen = (*env)->GetArrayLength(env, byteArray);     jbyte *jBuf = (*env)->GetByteArrayElements(env, byteArray, JNI_FALSE);     if (jBuf > 0)     {         pStr = (char*)malloc(strLen + 1);         if (!pStr)         {             return NULL;         }         memcpy(pStr, jBuf, strLen);         pStr[strLen] = 0;     }     env->ReleaseByteArrayElements(byteArray, jBuf, 0);     return pStr; }

实例二

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 #include <string.h> #include <jni.h> #include <stdio.h>   jbyteArray decryto                  (JNIEnv *env,                   jobject jclazz,                   jbyteArray paramArrayOfByte,                   jstring paramString) {     jclass jc_SecureRandom =         (*env)->FindClass(env, "java/security/SecureRandom");     jmethodID jm_constructor =         (*env)->GetMethodID(env, jc_SecureRandom, "<init>", "()V");     jobject jo_SecureRandom =         (*env)->NewObject(env, jc_SecureRandom, jm_constructor);       jclass  jc_DESKeySpec =         (*env)->FindClass(env, "javax/crypto/spec/DESKeySpec");     jmethodID jm_DESKeySpec =         (*env)->GetMethodID(env, jc_DESKeySpec, "<init>", "([B)V");     //DESKeySpec函数的参数是byte[] 返回值是void       jclass jc_string = (*env)->FindClass(env, "java/lang/String");     jmethodID jm_getBytes =         (*env)->GetMethodID(env, jc_string, "getBytes", "()[B");     //参数为空,返回值为byte[]     jbyteArray jb_paramString =         (jbyteArray)(*env)->CallObjectMethod(env, paramString, jm_getBytes);       jobject jo_DESKeySpec =         (*env)->NewObject(env, jc_DESKeySpec, jm_DESKeySpec, jb_paramString);     //new DESKeySpec(ArrayOfByte);       jclass jc_SecretKeyFactory =         (*env)->FindClass(env, "javax/crypto/SecretKeyFactory");     jmethodID jm_getInstance =         (*env)->GetMethodID(env, jc_SecretKeyFactory,"getInstance",                     "(Ljava/lang/String;)Ljavax/crypto/SecretKeyFactory;");     //getInstance的参数是string,返回值是一个SecretKeyFactory     jobject jo_SecretKeyFactory =         (*env)->CallStaticObjectMethod(env, jc_SecretKeyFactory,                              jm_getInstance,(*env)->NewStringUTF(env, "DES"));       jmethodID jm_generateSecret =         (*env)->GetMethodID(env, jc_SecretKeyFactory, "generateSecret",                 "(Ljava/security/spec/KeySpec;)Ljavax/crypto/SecretKey;");      //generateSecret的参数是一个keyspec,返回值是一个secretKey     jobject jo_SecretKey =         (*env)->CallObjectMethod(env, jc_SecretKeyFactory,                                       jm_generateSecret, jo_DESKeySpec);       jclass jc_Cipher = (*env)->FindClass(env, "javax/crypto/Cipher");     jmethodID jm_Cipher_getInstance =         (*env)->GetStaticMethodID(env, jc_Cipher, "getInstance",                              "(Ljava/lang/String;)Ljavax/crypto/Cipher;");     //参数是一个string, 返回值是一个Cipher     jobject jo_Cipher =         (*env)->CallStaticObjectMethod(env, jc_Cipher,                  jm_Cipher_getInstance, (*env)->NewStringUTF(env, "DES"));       jmethodID jm_Cipher_init =         (*env)->GetMethodID(env, jc_Cipher, "init",                     "(ILjava/security/Key;Ljava/security/SecureRandom;)V");     (*env)->CallVoidMethod(env, jc_Cipher, jm_Cipher_init, 2,                                           jo_SecretKey, jo_SecureRandom);       jmethodID jm_Cipher_doFinal =         (*env)->GetMethodID(env, jc_Cipher, "doFinal", "([B)[B");     //参数是byte[]  返回值也是byte[]     jbyteArray jb_Resultarr =         (*env)->CallObjectMethod(env, jc_Cipher, jm_Cipher_doFinal,                                                     paramArrayOfByte);     //最终结果就保存在jb_Resultarr       return jb_Resultarr; }   JNIEXPORT jbyteArray JNICALL     Java_com_qihoo_test_first_MainActivity_decry                                                 (JNIEnv *env,                                                  jobject thiz,                                                  jbyteArray paramArrayOfByte,                                                  jstring paramString)   {       return decryto(env, thiz, paramArrayOfByte, paramString);   }

 

 

本文出自 0n1y3nd"s Blog,转载时请注明出处及相应链接。

本文永久链接: http://0nly3nd.sinaapp.com/?p=277

声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。