Step By Step(Java 本地方法篇) (八)

2014-11-24 03:21:35 · 作者: · 浏览: 3
D@13f3045

21 0.0 2.0 4.0 6.0 8.0 10.0 12.0 14.0 16.0 18.0

22 */

12. 异常错误处理:

在Java编程语言中,可以通过异常中断当前正在执行的操作,并退出当前操作所在的函数。然而当我们使用native方法的时候,由于是C语言并不支持异常,这样便需要JNI提供一组操作Java异常的方法,以便在二者之间可以共享异常信息。需要注意的是,即便C++中支持异常,也无法将C++中的异常和Java中的直接关联在一起,更无法在两者之间相互转换。这里我们还是通过代码示例的方式,并结合关键的注释来了解这些JNI函数的用法和机制。

1) 包含native方法的Java类代码:

1 import java.io.PrintWriter;

2 public class Printf {

3 public static native void fprint(PrintWriter ps,String format,double x);

4 static {

5 System.loadLibrary("Printf");

6 }

7 }

2) 实现本地方法的C语言代码:

1 #include "Printf.h"

2 #include

3 #include

4 #include

5 JNIEXPORT void JNICALL Java_Printf_fprint

6 (JNIEnv* env, jclass cl, jobject out, jstring format, jdouble x)

7 {

8 //这里是通过ThrowNew方法生成一个异常对象,这里FindClass查找的是

9 //运行时异常NullPointerException,需要注意的是,对于C语言的代码,

10 //在调用ThrowNew之后,并不会在C代码内部抛出异常,因此在调用ThrowNew后,

11 //其后面的代码仍然可以继续执行。然而由于异常标识一种错误的状态,因此

12 //在通常情况下,我们都会在ThrowNew的后面释放一些资源,之后立刻调用

13 //return退出当前的native方法。

14 //在native方法退出后,其调用的ThrowNew将会发挥作用,JVM会将抛出的

15 //异常返给native方法的最近调用者(Java代码)。

16 if (format == NULL) {

17 env->ThrowNew(env->FindClass("java/lang/NullPointerException"),

18 "Printf.fprint: format is NULL");

19 return;

20 }

21 const char* cformat = env->GetStringUTFChars(format,NULL);

22 char* cstr = (char*)calloc(strlen(cformat) + 20,sizeof(char));

23 if (cstr == NULL) {

24 env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError")

25 ,"Printf.fprint: malloc failed");

26 return;

27 }

28 sprintf(cstr,cformat,x);

29 env->ReleaseStringUTFChars(format,cformat);

30 //调用PrintWriter.print(char)方法。

31 jclass class_PrintWriter = env->GetObjectClass(out);

32 jmethodID id_print = env->GetMethodID(class_PrintWriter,"print","(C)V");

33 //ExceptionOccurred将返回Java中抛出的异常,如果为NULL则表示没有异常出现。

34 //如果不希望知道具体的异常,可以调用jboolean ExceptionCheck()方法来判断

35 //是否异常发生了。如果C语言的代码在获悉异常的类型后,可以自行处理该异常,

36 //那么在处理之后,需要调用JNI函数ExceptionClear()来清除JVM传递过来的异常。

37 for (int i = 0; cstr[i] != 0 && !env->ExceptionOccurred(); ++i) {

38 env->CallVoidMethod(out,id_print,cstr[i]);

39 }

40 free(cstr);

41 }

3) 含有main函数的调用测试代码:

1 import java.io.PrintWriter;

2 public class MyTest {

3 public static void main(String[] args) throws Exception {

4 double price = 44.95;

5 double tax = 7.75;

6 double amountDue = price * (1 + tax / 100);

7 PrintWriter out = new PrintWriter(System.out);

8 //This call will throw an exception

9 Printf.fprint(out, "Amount due = %%8.2f\n", amountDue);

10 out.flush();

11 }

12 }

作者 Stephen_Liu