分享

Android JNI实例代码(二)

 开花结果 2011-04-26
我们继续Android JNI开发中的常用代码,第二部分将包含如何在JNI中构造实例化一个Java类以及异常处理的具体方法,有关前一部分的内容可以查看Android JNI实例代码(一) 。
   三、在JNI中构造和实例化Java类
view plaincopy to clipboardprint?
public class AndroidJniDemo4{  
 public static native void constructClass(); //JNI方法  
 public static void main(String[] args){  
  AndroidJniDemo4.constructClass();  
 }  
}  
class CwjThread implements Runnable {  
 int nCount = 0 ;  
 public void run(){  
  try{  
   Thread.sleep(1987); //休眠1987毫秒  
  }catch(Exception e){  
   e.printStackTrace();  
  }  
  System.out.println("Count="+ nCount);  
 }  

public class AndroidJniDemo4{
 public static native void constructClass(); //JNI方法
 public static void main(String[] args){
  AndroidJniDemo4.constructClass();
 }
}
class CwjThread implements Runnable {
 int nCount = 0 ;
 public void run(){
  try{
   Thread.sleep(1987); //休眠1987毫秒
  }catch(Exception e){
   e.printStackTrace();
  }
  System.out.println("Count="+ nCount);
 }
}
JNI代码:
view plaincopy to clipboardprint?
JNIEXPORT void JNICALL  
Java_AndroidJniDemo4_constructClass(JNIEnv *env, jclass clazz){  
 jclass jclazz , cwjclazz;   
 jmethodID mid , mid2 , runmid ;  
   
 jobject obj , obj2 ;  
 jclazz = (*env)->FindClass(env, "CwjThread");   //查找Java层的类  
 if (jclazz == NULL)  
 {  
  return ;  
 }  
 mid = (*env)->GetMethodID(env, jclazz,"<init>", "()V"); //构造CwjThread类  
   
 if (mid == NULL)  
 {  
  return ;  
 }  
 obj = (*env)->NewObject(env, jclazz, mid, NULL); //创建该类的实例,生成的新对象为obj  
 cwjclazz = (*env)->FindClass(env, "Ljava/lang/Thread;"); ////得到Thread类  
 if (cwjclazz == NULL)  
 {  
  return ;  
 }   
   
 mid2 = (*env)->GetMethodID(env, cwjclazz,"<init>", "(Ljava/lang/Runnable;)V"); //获取Runnable方法ID  
   
 if (mid2 == NULL)  
 {  
  return ;  
 }  
 obj2 = (*env)->NewObject(env, cwjclazz, mid2, obj);  //构造Runnable对象  
 runmid = (*env)->GetMethodID(env, cwjclazz,"start", "()V");  //获取Runable对象的start方法ID  
   
 if (runmid == NULL)  
 {  
  return ;  
 }  
 (*env)->CallVoidMethod(env, obj2, runmid);   //执行start方法在JNI中,来启动线程  
 (*env)->DeleteLocalRef(env, jclazz);  //我们并没有使用NewLocalRef有关本地引用的内容Android123在 Android JNI开发终极篇中将详细讲述  

JNIEXPORT void JNICALL
Java_AndroidJniDemo4_constructClass(JNIEnv *env, jclass clazz){
 jclass jclazz , cwjclazz;
 jmethodID mid , mid2 , runmid ;
 
 jobject obj , obj2 ;
 jclazz = (*env)->FindClass(env, "CwjThread");   //查找Java层的类
 if (jclazz == NULL)
 {
  return ;
 }
 mid = (*env)->GetMethodID(env, jclazz,"<init>", "()V"); //构造CwjThread类
 
 if (mid == NULL)
 {
  return ;
 }
 obj = (*env)->NewObject(env, jclazz, mid, NULL); //创建该类的实例,生成的新对象为obj
 cwjclazz = (*env)->FindClass(env, "Ljava/lang/Thread;"); ////得到Thread类
 if (cwjclazz == NULL)
 {
  return ;
 }
 
 mid2 = (*env)->GetMethodID(env, cwjclazz,"<init>", "(Ljava/lang/Runnable;)V"); //获取Runnable方法ID
 
 if (mid2 == NULL)
 {
  return ;
 }
 obj2 = (*env)->NewObject(env, cwjclazz, mid2, obj);  //构造Runnable对象
 runmid = (*env)->GetMethodID(env, cwjclazz,"start", "()V");  //获取Runable对象的start方法ID
 
 if (runmid == NULL)
 {
  return ;
 }
 (*env)->CallVoidMethod(env, obj2, runmid);   //执行start方法在JNI中,来启动线程
 (*env)->DeleteLocalRef(env, jclazz);  //我们并没有使用NewLocalRef有关本地引用的内容Android123在 Android JNI开发终极篇中将详细讲述
}
上面的代码可能我们发现JNI中构造一个类比Java层麻烦的多,需要先获取ID,测试是否为空,然后编写类方法的构造和类型签名符号,多了很多这样的操作,不过Android开发网提醒大家毕竟JNI中没有类的声明引用,只有动态获取这些方法的ID所以执行效率可能比Java还有所降低,类似Java反射一样的处理机制,希望大家明白这个道理。
四、JNI中的异常处理实例代码
view plaincopy to clipboardprint?
class AndroidJniDemo5 {  
 private native void createException() throws IllegalArgumentException; //JNI中抛出一个参数不合法异常  
 private void throwException() throws NullPointerException {  
  throw new NullPointerException("Java error, android123 "); //Java中产生一个空指针异常  
 }  
 public static void main(String args[]) {  
  AndroidJniDemo5 ajd5 = new AndroidJniDemo5();  
  try {  
   ajd5.createException();   
  } catch (Exception e) {  
     e.printStackTrace();  
  }  
 }  
 static {  
  System.loadLibrary("AndroidJniDemo5");  
 }  

class AndroidJniDemo5 {
 private native void createException() throws IllegalArgumentException; //JNI中抛出一个参数不合法异常
 private void throwException() throws NullPointerException {
  throw new NullPointerException("Java error, android123 "); //Java中产生一个空指针异常
 }
 public static void main(String args[]) {
  AndroidJniDemo5 ajd5 = new AndroidJniDemo5();
  try {
   ajd5.createException();
  } catch (Exception e) {
     e.printStackTrace();
  }
 }
 static {
  System.loadLibrary("AndroidJniDemo5");
 }
}
下面的JNI中的异常具体代码
view plaincopy to clipboardprint?
JNIEXPORT void JNICALL  
Java_AndroidJniDemo5_createException(JNIEnv *env, jobject obj)  
{  
 jthrowable throwable;  
 jclass clazz = (*env)->GetObjectClass(env, obj);  
 jmethodID mid = (*env)->GetMethodID(env, clazz, "throwException", "()V"); //获取Java中的throwException方法ID  
 if (mid == NULL)  
 {  
  return;  
 }  
 (*env)->CallVoidMethod(env, obj, mid); //执行throwException方法  
 throwable = (*env)->ExceptionOccurred(env);  //有异常发生,其实Android123提醒大家还可以使用JNI中的异常检测ExceptionCheck函数来判断  
 if (throwable)  // 如果发生了异常  
 {  
  jclass newExceptionClazz;  
  (*env)->ExceptionDescribe(env);  
  (*env)->ExceptionClear(env);  
  newExceptionClazz = (*env)->FindClass(env,"java/lang/IllegalArgumentException"); //实例化一个参数不合法异常  
  if (newExceptionClazz == NULL)  
  {  
   return;  
  }  
  (*env)->ThrowNew(env, newExceptionClazz, "JNI cwj exception"); //在JNI中抛出异常  
 }  

JNIEXPORT void JNICALL
Java_AndroidJniDemo5_createException(JNIEnv *env, jobject obj)
{
 jthrowable throwable;
 jclass clazz = (*env)->GetObjectClass(env, obj);
 jmethodID mid = (*env)->GetMethodID(env, clazz, "throwException", "()V"); //获取Java中的throwException方法ID
 if (mid == NULL)
 {
  return;
 }
 (*env)->CallVoidMethod(env, obj, mid); //执行throwException方法
 throwable = (*env)->ExceptionOccurred(env);  //有异常发生,其实Android123提醒大家还可以使用JNI中的异常检测ExceptionCheck函数来判断
 if (throwable)  // 如果发生了异常
 {
  jclass newExceptionClazz;
  (*env)->ExceptionDescribe(env);
  (*env)->ExceptionClear(env);
  newExceptionClazz = (*env)->FindClass(env,"java/lang/IllegalArgumentException"); //实例化一个参数不合法异常
  if (newExceptionClazz == NULL)
  {
   return;
  }
  (*env)->ThrowNew(env, newExceptionClazz, "JNI cwj exception"); //在JNI中抛出异常
 }
}
 最后我们可以看到在JNI中处理很多事情确实需要编写很多代码,同时有关类的构造符号什么的,目前的IDE和编译器无法检查,所以Android开发网提醒大家一定要记住Java签名符号的格式和规范,下一次我们给出一些例子,帮助Android NDK初学者快速了解JNI的规则。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多