JNI(2)

JNI(2)

访问字段和方法

JNI允许本地代码访问java 对象的字段和方法。
调用需要两个步骤:
例如调用cls类的f方法,
1. 获取方法ID

jmethodID mid =      env->GetMethodID(cls, “f”, “(ILjava/lang/String;)D”);

2. 然后本地方法可以重复的使用方法ID

jdouble result = env->CallDoubleMethod(obj, mid, 10, str);



报告编程错误

JNI 不会检查编程错误,例如传递null指针或者非法的类型参数。 非法的类型参数包括使用普通对象代替类对象,JNI不检查这些错误的原因是:

  •  检查所有可能的错误会降低本地方法的性能
  •  在很多情况下,没有足够多的运行时信息去做检查
大部分的C库都不会保证一定没有编程错误。例如 printf()方法,当它接收到一个无效的地址时,导致运行时异常,而不是返回一个错误码。


Java 异常

JNI允许本地方法抛出java 异常。本地方法也可以处理java 异常之外的异常。没有处理的java 异常会返回到VM。


异常和错误代码

JNI方法报告错误的方式:通过返回错误码和抛出java 异常。
编程者可以:
  • 根据最后一次JNI调用返回的值判断时候发生了错误
  • 调用一个方法,获取异常对象的详细描述信息。
有两种情况,程序员检查异常不可以先检查错误码:
  • JNI调用java返回结果的方法。必须调用ExceptionOccurred()去检查在java方法运行的时候可能产生的异常。
  • 一些JNI数组访问方法不会返回错误码。但是可能抛出ArrayIndexOutOfBoundsException或者ArrayStoreException.

异步异常

在多线程的情况下,当前线程的线程可能会抛出异步异常。异步异常不会马上影响在当前线程执行的本地方法,直到:
  • 本地方法调用JNI方法时,能够抛出异步异常,或者
  • 本地方法明确使用ExceptionOccurred()检查同步和异步异常。

异常处理

在本地方法中有两种方式可以处理异常:

  • 本地方可以抛出java异常
  • 本地方法可以调用ExceptionClear()清楚异常,然后执行自己的异常处理。
当一个异常抛出,本地代码必须先清除异常,然后才能调用其他的JNI方法。当有一个挂起的异常时,JNI方法可以安全的调用:
  ExceptionOccurred()
  ExceptionDescribe()
  ExceptionClear()
  ExceptionCheck()
  ReleaseStringChars()
  ReleaseStringUTFChars()
  ReleaseStringCritical()
  Release<Type>ArrayElements()
  ReleasePrimitiveArrayCritical()
  DeleteLocalRef()
  DeleteGlobalRef()
  DeleteWeakGlobalRef()
  MonitorExit()
  PushLocalFrame()
  PopLocalFrame()




你可能感兴趣的:(java,jni)