例如,对于 Java 程序而言,通过抛出一个异常来向 JVM报告出错是常见和正确的操作。C 没有异常,因此必须使用 JNI 的异常处理函数。
有两种方法用来在本机代码中抛出异常:可以调用 Throw()
ThrowNew()
Throw()
Throwable
ThrowNew()
IOException
:
1.
2. jclass cls = (*env)->FindClass(env, "java/io/IOException");
3. jmethodID mid = (*env)->GetMethodID(env, cls, "", "()V");
4. jthrowable e = (*env)->NewObject(env, cls, mid);
5.
6.
7. (*env)->Throw(env, e);
8. ...
9.
10.
11. (*env)->ThrowNew(env,
12. (*env)->FindClass("java/io/IOException"),
13. "An IOException occurred!");
|
Throw()
ThrowNew()
Throw()
ThrowNew()
Throw()
ThrowNew()
当从 C 或 C++ 调用 Java 时,也可能需要捕获异常。 许多JNI 函数都能抛出希望捕获的异常。ExceptionCheck()
jboolean
以表明是否抛出了异常,而 ExceptionOccured()
jthrowable
NULL
,如果未抛出异常的话)。
如果正在捕获异常,可能要处理异常,在这种情况下需要在 JVM中清除该异常。可以使用 ExceptionClear()
ExceptionDescribed()
在使用 JNI工作时,您将遇到的更高级的问题之一是在本机方法中使用多线程。即使是在不需要支持多线程的系统上运行时,Java平台也是作为多线程系统来实现的;因此您有责任确保本机函数是线程安全的。
在 Java程序中,可以通过使用 synchronized
synchronized
synchronized
JNI使用 MonitorEnter()
MonitorExit()
MonitorEnter()
MonitorExit()
MonitorEnter()
MonitorExit()
下表显示了如何在 Java、C 和 C++中同步一块代码。正如您所见,这些 C 和 C++ 函数类似于 Java代码中的 synchronized
XML error: The image is notdisplayed because the width is greater than the maximum of 580pixels. Please decrease the image width. |
确保本机方法同步的另一种方法是:当在 Java类中声明 native
synchronized
使用 synchronized
native
synchronized
。尽管用 synchronized
- C 或 C++ 代码和 Java本机方法声明不同,因此,如果方法声明有变动(即,如果一旦除去了
synchronized
关键字),此方法可能马上不再是线程安全的了。
- 如果有人对使用该函数的其它本机方法(或其它 C 或 C++函数)进行编码,他们可能并没有意识到该本机实现不是线程安全的。
- 如果将函数作为普通的 C 函数在 Java程序之外使用,则它不是线程安全的。
Object.wait()
、Object.notify()
Object.notifyAll()
Object