(JNI)c代码利用反射调用java方法

转自http://blog.csdn.net/u012739481/article/details/50978091

反射一般分3个步骤:
1.加载calss(字节码),获取class的对象。
2.获取对应的方法或属性。
3.修改属性,或执行方法。


首先回顾一下java中的反射    写一个类JK:
[java]  view plain  copy
  1. public class Jk {  
  2.   
  3.      public void p(String s) {  
  4.           System. out.println(s);  
  5.      }  
  6. }  

另一个Test类来反射此类,执行p(String)方法:
[java]  view plain  copy
  1. public class Test {  
  2.      public static void main(String[] args) {  
  3.            try {  
  4.               Class clazz = Test.class.getClassLoader().loadClass("Jk" );  
  5.               Method method = clazz.getDeclaredMethod("p" ,  
  6.                          new Class[] { String.class });  
  7.               method.invoke(clazz.newInstance(), new String[] { "java反射" });  
  8.           } catch (Exception e) {  
  9.               e.printStackTrace();  
  10.           }  
  11.      }  
  12. }  


控制台输出:          java反射  
c代码利用反射调用java方法:   目标:在MainActivity中放一个按钮,点击按钮,按钮执行native 方法jk();c语言jk()函数反射执行MainActivity中的jkShow()方法,jkShow()方法弹出Toast。        1.MainActivity.java类
[java]  view plain  copy
  1. public class MainActivity extends Activity {  
  2.      static{  
  3.           System. loadLibrary("jk");  
  4.      }  
  5.   
  6.      @Override  
  7.      protected void onCreate(Bundle savedInstanceState) {  
  8.            super.onCreate(savedInstanceState);  
  9.           setContentView(R.layout. activity_main);  
  10.      }  
  11.   
  12.      public void onclick(View view) {  
  13.           jk();  
  14.      }  
  15.   
  16.      public native void jk();  
  17.   
  18.      public void jkShow(String message) {  
  19.           Toast. makeText(this, message, 0).show();  
  20.      }  
  21. }  


  2.jk.c
[java]  view plain  copy
  1. #include <jni.h>  
  2. //c代码利用反射调用java方法  
  3. JNIEXPORT void JNICALL Java_com_jk184_cj_MainActivity_jk(JNIEnv * env,  
  4.            jobject jobj) {  
  5. //1.获取对应的class  
  6. //   jclass      (*FindClass)(JNIEnv*, const char*);  
  7.      jclass clazz = (*env)-> FindClass(env, "com/jk184/cj/MainActivity" );  
  8. //2.获取对应的方法  
  9.      //c语言是获取方法的id  
  10. //   jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);  
  11.      jmethodID jmID = (*env)-> GetMethodID(env, clazz, "jkShow",  
  12.                "(Ljava /lang/String;)V" );  
  13. //3.执行方法  
  14. //     void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);  
  15.      (*env)-> CallVoidMethod(env, jobj, jmID,  
  16.               (*env)-> NewStringUTF(env, "这是c反射调用java方法" ));  
  17. }  


注意:
[java]  view plain  copy
  1. (*env)-> GetMethodID(env, clazz, "jkShow",  
  2.                "(Ljava /lang/String;)V" );  
最有一个参数是方法的签名,具体规范百度。 可在bin/classes下执行 javap -s 类名(com.jk184.cj.MainActivity)  获得类下面所有方法的签名。 
[java]  view plain  copy
  1. (*env)-> CallVoidMethod(env, jobj, jmID,  
  2.               (*env)-> NewStringUTF(env, "这是c反射调用java方法" ));  
最后一个使用字符串,需要注意两点: 1.不能直接使用字符串 (c和java的类型不一致) 2.使用中文要注意c文件是UTF-8编码。(否则乱码报错) 

第一次写csdn,初学jni,请抱着怀疑的心态看此文。   最后有错请指教...  
posted @ 2017-11-29 22:06  Mr.zzz  阅读(69)  评论(0编辑  收藏  举报