java jni笔记

  1. 在java中定义native method
    • public native void set_intValue(int selfHashCode, int v);
  2. 从java中生成C++用头文件
    • javah -jni -classpath bin -d hdr HelloWorld
  3. C++ project的配置
    • include目录 c:\Program Files\Java\jdk1.7.0_02\include
    • include目录 c:\Program Files\Java\jdk1.7.0_02\include\win32
    • include目录 对应javaclass.h的位置
  4. C++中基本类型
    1. JNIENV - java的运行环境
    2. jobject - 代表java的instance
    3. jclass - 代表java的类
  5. 基本使用
    • 在java中load C++的native 库
      System.loadLibrary("myjnilib");
    • C++ :根据jobject获取其jclass
      jclass cls = (*env)->GetObjectClass(env, obj);
    • C++ , 获取methodId
          jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "(I)V");
          if (mid == 0) {
              return;
          }
    • C++, 调用Java method
      • (*env)->CallVoidMethod(env, obj, mid, depth);
      • 其他返回类型的调用参见JNIENV的定义
    • C++, 访问java的String
      • JNIEXPORT jstring JNICALL
        Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt)
        {
            char buf[128];
            const char *str = (*env)->GetStringUTFChars(env, prompt, 0);
            printf("%s", str);
            (*env)->ReleaseStringUTFChars(env, prompt, str);
    • C++, 由C++String 到 java String
      •  ...
            scanf("%s", buf);
            return (*env)->NewStringUTF(env, buf);
        }
      • 其他String相关的function
        • GetStringChars takes the Java string and returns a pointer to an array of Unicode characters that comprise the string.
        • ReleaseStringChars releases the pointer to the array of Unicode characters.
        • NewString constructs a new java.lang.String object from an array of Unicode characters.
        • GetStringLength returns the length of a string that is comprised of an array of Unicode characters.
        • GetStringUTFLength returns the length of a string if it is represented in the UTF-8 format
    • C++, 访问java Array
      • JNIEXPORT jint JNICALL
        Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)
        {
            int i, sum = 0;
            jsize len = (*env)->GetArrayLength(env, arr);
            ...
      • 访问array的元素
        • GetObjectArrayElement returns the object element at a given index.
        • SetObjectArrayElement updates the object element at a given index
        jint *body = (*env)->GetIntArrayElements(env, arr, 0);
            for (i=0; i<len; i++) {
                sum += body[i];
            }
      • 释放
      • (*env)->ReleaseIntArrayElements(env, arr, body, 0);
            return sum;
        
    • C++, 访问Java field
      • //get field id
        fid = (*env)->GetStaticFieldID(env, cls, "si", "I");
        fid = (*env)->GetFieldID(env, cls, "s", "Ljava/lang/String;");
        //get field value
        si = (*env)->GetStaticIntField(env, cls, fid);
        jstr = (*env)->GetObjectField(env, obj, fid);
         
    • C++, 处理java中的Exception
      • JNIEXPORT void JNICALL 
        Java_CatchThrow_catchThrow(JNIEnv *env, jobject obj)
        {
          jclass cls = (*env)->GetObjectClass(env, obj);
          jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "()V");
          jthrowable exc;
          if (mid == 0) {
            return;
          }
          (*env)->CallVoidMethod(env, obj, mid);
          exc = (*env)->ExceptionOccurred(env);
          if (exc) {
            /* We don't do much with the exception, except that we print a
               debug message using ExceptionDescribe, clear it, and throw
               a new exception. */
            jclass newExcCls;
        
            (*env)->ExceptionDescribe(env);
            (*env)->ExceptionClear(env);
        
            newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
            if (newExcCls == 0) { /* Unable to find the new exception class, give up. */
              return;
            }
            (*env)->ThrowNew(env, newExcCls, "thrown from C code");
          }
        }
      • It is extremely important to check, handle, and clear the pending exception before calling subsequent JNI functions. Calling arbitrary JNI functions with a pending exception may lead to unexpected results. You can safely call only a small number of JNI functions when there is a pending exception. These functions are ExceptionOccurred, ExceptionDescribe, and ExceptionClear.
    • 线程
        • The JNI interface pointer (JNIEnv *) is only valid in the current thread.
        • You must not pass local references from one thread to another. In particular, a local reference may become invalid before the other thread has had a chance to use it. You should always convert local references to global references in situations where different threads may be using the same reference to a Java object.
        • Check the use of global variables carefully. Multiple threads might be accessing these global variables at the same time. Make sure you put in appropriate locks to ensure safety.
        • Native code can perform equivalent synchronization on objects using the JNI functions MonitorEnter andMonitorExit. For example:
        • ...
          (*env)->MonitorEnter(env, obj);
          ...                      /* synchronized block */
          (*env)->MonitorExit(env, obj);
          ...
    • C++, 根据名字查找类
      • jclass cls = env->FindClass("java/lang/String");

posted on 2012-03-14 21:58  learner  阅读(742)  评论(0)    收藏  举报

导航