JNI中调用JAVA各种方法详解
总结一下 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”);
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[][][],即几维数组就加几个[

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 |
12345678 | SecureRandom 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
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。