作者:左少华
博客:http://blog.csdn.net/shaohuazuo/article/details/42932813
转载请注明出处:http://blog.csdn.net/shaohuazuo

一:struct JNINativeInterface_{}

  结构体的作用:它有点像我们char字符驱动的 file_ops结构体,它定义各种函数对在(jni.h头文件详解一)中定义的各种数据的操作函数集体.

二:它包含那些针对Java中类和对象的相关操作呢如下图.

  

三:下面我们讲详细介绍14个部分方法的用法和解析

3.1.版本信息操作函数.

一.GetVersion

jint (JNICALL *GetVersion)(JNIEnv *env)

--模块信息:该模块主要针对的JNI接口的版本信息操作函数.

函数原型:jint (JNICALL *GetVersion)(JNIEnv *env)

 描 述:它用来返回jni的版本信息.version = (*env)->GetVersion(env);   
     我们通过这个方法获取版本信息.并通过回调java的getVersion()方法显示版本号. 
 参 数:这个JNIEnv是JNI的运行环境.这个环境中包含了上图的14大块的操作函数等等.
 返回值:返回一个0-65535大小的数.他是一个16位的正整数.高八位是主版本号.低八位是次版本号.
  例 程:

--1.1 函数使用Demo流程介绍.

     通过Java对象的构造方法,把当前对象传递到C中.C获取到该对象之后,保存Java对象的引用,并获取相应的方法等.

     获取该对象之后,C会调用获取JNI版本的函数.获取版本号,并调用Java层的getVersion()函数,将版本号显示出来.如图:

--1.2 代码
  1. package com.octopus.test03;
  2. import android.os.Bundle;
  3. import android.app.Activity;
  4. import android.graphics.Color;
  5. import android.view.Menu;
  6. import android.view.View;
  7. import android.view.View.OnClickListener;
  8. import android.widget.Button;
  9. import android.widget.LinearLayout;
  10. import android.widget.TextView;
  11. public class Act1 extends Activity implements OnClickListener {
  12. private final int WC = LinearLayout.LayoutParams.WRAP_CONTENT;
  13. private final int FP = LinearLayout.LayoutParams.FILL_PARENT;
  14. private Button btn, btn3;
  15. public static Act1 ref;
  16. public TextView tv;
  17. @Override
  18. protected void onCreate(Bundle icicle) {
  19. super.onCreate(icicle);
  20. ref = this;
  21. LinearLayout layout = new LinearLayout(this);
  22. layout.setOrientation(LinearLayout.VERTICAL);
  23. btn = new Button(this);
  24. btn.setId(101);
  25. btn.setText("run(Adder)");
  26. btn.setBackgroundResource(R.drawable.ic_launcher);
  27. btn.setOnClickListener(this);
  28. LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(120, 50);
  29. param.topMargin = 10;
  30. layout.addView(btn, param);
  31. btn3 = new Button(this);
  32. btn3.setId(103);
  33. btn3.setText("exit");
  34. btn3.setBackgroundResource(R.drawable.ic_launcher);
  35. btn3.setOnClickListener(this);
  36. layout.addView(btn3, param);
  37. tv = new TextView(this);
  38. tv.setTextColor(Color.WHITE);
  39. tv.setText("");
  40. LinearLayout.LayoutParams param2 = new LinearLayout.LayoutParams(FP, WC);
  41. param2.topMargin = 10;
  42. layout.addView(tv, param2);
  43. setContentView(layout);
  44. }
  45. public void onClick(View v) {
  46. if (v == btn) {
  47. int a = 1, b = 1;
  48. GetVersion adder = new GetVersion();
  49. } else if (v == btn3) {
  50. finish();
  51. }
  52. }
  53. @Override
  54. public boolean onCreateOptionsMenu(Menu menu) {
  55. // Inflate the menu; this adds items to the action bar if it is present.
  56. getMenuInflater().inflate(R.menu.main, menu);
  57. return true;
  58. }
  59. }
--1.3 Jni层代码
  1. package com.octopus.test03;
  2. import java.lang.ref.WeakReference;
  3. import android.os.Handler;
  4. import android.os.Message;
  5. public class GetVersion {
  6. private static Handler h;
  7. static {
  8. System.loadLibrary("HelloNdk");
  9. }
  10. public GetVersion() {
  11. h = new Handler() {
  12. public void handleMessage(Message msg) {
  13. Act1.ref.setTitle(msg.obj.toString());
  14. }
  15. };
  16. nativeSetup(new WeakReference<GetVersion>(this));
  17. }
  18. private static void getVersion(Object version_ref, int what,int message)
  19. {
  20. String obj1 = "Jni Version is : "+ message;
  21. Message m = h.obtainMessage(what, obj1);
  22. h.sendMessage(m);
  23. }
  24. private native void nativeSetup(Object weak_this);
  25. }
--1.4 C 层代码
  1. 1 /* DO NOT EDIT THIS FILE - it is machine generated */
  2. 2 #include "com_octopus_test03_GetVersion.h"
  3. 3 /* Header for class com_octopus_test03_GetVersion */
  4. 4
  5. 5 /*
  6. 6  * Class:     com_octopus_test03_GetVersion
  7. 7  * Method:    nativeSetup
  8. 8  * Signature: (Ljava/lang/Object;)V
  9. 9  */
  10. 10
  11. 11 jclass mClass;
  12. 12 jobject mObject;
  13. 13 jmethodID mid;
  14. 14
  15. 15 JNIEXPORT void JNICALL Java_com_octopus_test03_GetVersion_nativeSetup
  16. 16   (JNIEnv *env, jobject this, jobject weak_this)
  17. 17 {
  18. 18     jint version =0;
  19. 19     jclass class = (*env)->GetObjectClass(env,this);
  20. 20     mClass =  (jclass)(*env)->NewGlobalRef(env,class);
  21. 21     mObject = (*env)->NewGlobalRef(env,weak_this);
  22. 22     mid = (*env)->GetStaticMethodID(env, mClass,"getVersion","(Ljava/lang/Object;II)V");
  23. 23
  24. 24     version = (*env)->GetVersion(env);   //我们通过这个方法获取版本信息.并通过回调java的getVersion()方法显示版本号.
  25. 25     (*env)->CallStaticVoidMethod(env,mClass,mid,mObject,1,version);
  26. 26     return ;
  27. 27 }
1.5.Android.mk文件如下:
  1. SRC_PATH_ROOT:=$(LOCAL_PATH)/../../src
  2. LOCAL_PATH := $(call my-dir)
  3. include $(CLEAR_VARS)
  4. LOCAL_MODULE    := HelloNdk
  5. LOCAL_SRC_FILES := com_octopus_test03_GetVersion.c
  6. include $(BUILD_SHARED_LIBRARY)
--1.6 测试当前JNI的版本为65542

.

转载请说明出处:  http://blog.csdn.net/shaohuazuo/

.

3.2. 类模块相关操作.

(DefineClass,FindClass)

jclass (JNICALL *DefineClass)  (JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len);

jclass (JNICALL *FindClass) (JNIEnv *env, const char *name);

--模块信息:这个模块主要是C或者C++中如何获取Java的Class类对象. 这个接口再Android上没有得到支持.

一:DefineClass

函数原型:jclass (JNICALL *DefineClass)  (JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len);

 描 述: 从二进制的.class的数据缓冲区中加载类.

 参 数: env    java本地接口指针.

name   需要加载类的简短名称.比如下载需要加载一个com/zuoshaohua/Test.java这个类,那么该名称就是 Test

loader 类加载器对象.该类用来加载java字节码.class文件

buf    这个是字节码缓冲区数组.

len    该数组的长度.

返回值:

返回一个jclass类型的结构体.他对应的是Java中的类相关信息.

例 程:

--1.1 相关的java背景知识说.可以参考http://blog.csdn.net/lovingprince/article/details/4317069博客,

Java类加载器.也就是我们的loader参数的详细介绍.

在这里我们简单的说说loader的作用.在Java语言中loader是一个将 .class文件加载到内存的一个类加载器.

--1.2 例程的业务逻辑介绍:

写一个测试的java类.他用来输出一个字符串..我们把他编译成一个.class文件.然后使用DefineClass进行加载.

并再Activity中输出该字符串.

--1.3代码  (注释 界面代码和上一个实例是一样的.)
  1. package com.octopus.test03;
  2. import java.lang.ref.WeakReference;
  3. import android.os.Handler;
  4. import android.os.Message;
  5. public class DefindClassTest {
  6. ClassLoader loader;
  7. private static Handler h;
  8. static {
  9. System.loadLibrary("HelloNdk");
  10. }
  11. public DefindClassTest() {
  12. h = new Handler() {
  13. public void handleMessage(Message msg) {
  14. Act1.ref.setTitle(msg.obj.toString());
  15. }
  16. };
  17. loader = DefindClassTest.class.getClassLoader();
  18. if(loader==null){
  19. System.out.println("loader error\n");
  20. }
  21. //将获得的类加载器,传入到C层.
  22. nativeSetup(new WeakReference<ClassLoader>(loader));
  23. }
  24. private static void getVersion(Object version_ref, Object test, int what,int message)
  25. {
  26. String obj1 = "Jni Version is : "+ message+ "C Create obj is"+ test;
  27. Message m = h.obtainMessage(what, obj1);
  28. h.sendMessage(m);
  29. }
  30. private native void nativeSetup(Object weak_this);
  31. }
--1.4 jni中c端实现代码
  1. /* DO NOT EDIT THIS FILE - it is machine generated */
  2. #include "com_octopus_test03_DefindClassTest.h"
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <stdio.h>
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8. #include <fcntl.h>
  9. /*
  10. * Class:     com_octopus_test03_DefindClassTest
  11. * Method:    nativeSetup
  12. * Signature: (Ljava/lang/Object;)V
  13. */
  14. /*
  15. jclass (JNICALL *DefineClass) (JNIEnv *env, const char *name, jobject loader, const jbyte *buf,jsize len);
  16. */
  17. jclass mClass;
  18. jobject mObject;
  19. jmethodID mid;
  20. JNIEXPORT void JNICALL Java_com_octopus_test03_DefindClassTest_nativeSetup
  21. (JNIEnv *env, jobject this, jobject weak_this){
  22. int fd;
  23. off_t len;
  24. jint ret;
  25. int pos;
  26. off_t tmplen;
  27. jbyte *buf = NULL;
  28. jclass testclass;
  29. jint version =0;
  30. jobject mOjbect1;
  31. jobject obj1;
  32. jclass class = (*env)->GetObjectClass(env,this);
  33. mClass =  (jclass)(*env)->NewGlobalRef(env,class);
  34. //我们需要获取到DefineClassTest该类的类加载器.
  35. mObject = (*env)->NewGlobalRef(env,weak_this);
  36. //使用c读取我们需要加载的文件.
  37. fd = open("/system/Test.class",O_RDONLY);
  38. len = lseek(fd, 0, SEEK_END);
  39. buf = calloc(len,1);
  40. if(buf == NULL){
  41. printf("calloc error \n");
  42. return;
  43. }
  44. lseek(fd, 0,SEEK_SET);
  45. pos = 0;
  46. tmplen = len;
  47. while(tmplen > 0){
  48. ret += read(fd,buf+ret,tmplen-ret);
  49. pos +=ret;
  50. tmplen -=ret;
  51. }
  52. close(fd);
  53. //使用DefineClass函数加载这个类
  54. testclass = (*env)->DefineClass(env,"Test",mObject,buf,len);
  55. if(testclass == NULL)
  56. {
  57. return;
  58. }
  59. free(buf);
  60. obj1 = (*env)->AllocObject(env,testclass);
  61. //生成一个对象,并调用该对象的方法.
  62. mid = (*env)->GetStaticMethodID(env, mClass,"getVersion","(Ljava/lang/Object;Ljava/lang/Object;II)V");
  63. version = (*env)->GetVersion(env);
  64. (*env)->CallStaticVoidMethod(env,mClass,mid,this,obj1,1,version);
  65. return ;
  66. }

二: FindClass

函数原型:jclass (JNICALL *FindClass) (JNIEnv *env, const char *name);

 描 述: 该函数用于加载本地定义的类。它将搜索由CLASSPATH 环境变量为具有指定名称的类所指定的目录和 zip 文件。
          该CLASSPATH一般为:
           #set java environment
           JAVA_HOME=/home/xxx/java/jdk1.6.0_12
           export JRE_HOME=/home/xxx/java/jdk1.6.0_12/jre
           export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
           export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
           findClass函数的java背景知识在我的博客由介绍:

 参 数: env    java本地接口指针.
        name   需要加载类的简短名称.比如下载需要加载一个com/zuoshaohua/Test.java这个类,该参数就是 "com/zuoshaohua/Test"

返回值:
       返回一个jclass类型的结构体.他对应的是Java中的类相关信息.它是类的字节码对象. 

 例 程:

--2.1 流程:

    1.MainActivity的onCreate()方法中初始化一个ManPerson.

    2.在ManPerson的构造函数最后我们会调用nativeSetup把ManPerson对象传递到C中.

    3.我们会再C中得到ManPerson的属性Id信息,并保存起来.并使用findClass()方法获取Person类字节码对象,并生成Person对象的全集引用.

    4.当我们点击应用层的btn时,C会获取ManPerson的信息.使用bean的setXxx()给Person对象赋值.并返回给对象到java层.

   --2.2类图:

--2.3 Activity代码
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:paddingBottom="@dimen/activity_vertical_margin"
  6. android:paddingLeft="@dimen/activity_horizontal_margin"
  7. android:paddingRight="@dimen/activity_horizontal_margin"
  8. android:paddingTop="@dimen/activity_vertical_margin"
  9. tools:context=".MainActivity" >
  10. <TextView
  11. android:id="@+id/personView"
  12. android:layout_width="260dp"
  13. android:layout_height="100dp"
  14. android:layout_alignParentTop="true"
  15. android:layout_marginTop="28dp" />
  16. <Button
  17. android:id="@+id/exit"
  18. android:layout_width="100dp"
  19. android:layout_height="100dp"
  20. android:layout_alignBaseline="@+id/run"
  21. android:layout_alignBottom="@+id/run"
  22. android:layout_marginLeft="30dp"
  23. android:layout_toRightOf="@+id/run"
  24. android:text="EXIT" />
  25. <Button
  26. android:id="@+id/run"
  27. android:layout_width="100dp"
  28. android:layout_height="100dp"
  29. android:layout_alignLeft="@+id/personView"
  30. android:layout_below="@+id/personView"
  31. android:layout_marginLeft="31dp"
  32. android:layout_marginTop="22dp"
  33. android:text="RUN" />
  34. </RelativeLayout>
  1. package com.zuoshaohua;
  2. import com.zuoshaohua.ndk.ManPerson;
  3. import com.zuoshaohua.ndk.NativeExec;
  4. import com.zuoshaohua.ndk.Person;
  5. import android.os.Bundle;
  6. import android.app.Activity;
  7. import android.view.Menu;
  8. import android.view.View;
  9. import android.view.View.OnClickListener;
  10. import android.widget.Button;
  11. import android.widget.TextView;
  12. public class MainActivity extends Activity implements OnClickListener{
  13. private Button runbtn;
  14. private Button exitbtn;
  15. private ManPerson manPerson;
  16. private TextView  personView;
  17. @Override
  18. protected void onCreate(Bundle savedInstanceState) {
  19. super.onCreate(savedInstanceState);
  20. setContentView(R.layout.activity_main);
  21. exitbtn = (Button) this.findViewById(R.id.exit);
  22. runbtn = (Button) this.findViewById(R.id.run);
  23. personView = (TextView) this.findViewById(R.id.personView);
  24. manPerson = new ManPerson("zuoshaohua",33,"男");
  25. runbtn.setOnClickListener(MainActivity.this);
  26. exitbtn.setOnClickListener(this);
  27. }
  28. @Override
  29. public void onClick(View arg0) {
  30. int id = arg0.getId();
  31. switch (id) {
  32. case R.id.run:
  33. Person p = (Person)NativeExec.nativeExec();   //获取c代码生成对象.
  34. personView.setText("name ="+ p.getName()+ "age="+p.getAge()+"gender="+p.getGender()); //输出这个对象的值.
  35. break;
  36. case R.id.exit:
  37. this.finish();
  38. break;
  39. default:
  40. this.finish();
  41. break;
  42. }
  43. }
  44. }
 --2.4 jni代码
  1. package com.zuoshaohua.ndk;
  2. public class ManPerson {
  3. private String name;
  4. private int age;
  5. private String gender;
  6. static
  7. {
  8. System.loadLibrary("HelloNdk");         //加载动态库文件.
  9. }
  10. public ManPerson(String name, int age, String gender){
  11. this.name = name;
  12. this.age = age;
  13. this.gender =gender;
  14. nativeSetup();
  15. }
  16. private native void nativeSetup();
  17. }
  1. package com.zuoshaohua.ndk;
  2. public class NativeExec {
  3. public static native Object nativeExec();
  4. }
  1. package com.zuoshaohua.ndk;
  2. public class Person {
  3. private String name;
  4. private int age;
  5. private String gender;
  6. public String getName() {
  7. return name;
  8. }
  9. public void setName(String name) {
  10. this.name = name;
  11. }
  12. public int getAge() {
  13. return age;
  14. }
  15. public void setAge(int age) {
  16. this.age = age;
  17. }
  18. public String getGender() {
  19. return gender;
  20. }
  21. public void setGender(String gender) {
  22. this.gender = gender;
  23. }
  24. }
--2.5 c层代码
  1. #include "com_zuoshaohua_ndk_ManPerson.h"
  2. #include "com_zuoshaohua_ndk_NativeExec.h"
  3. /*
  4. * Class:     com_zuoshaohua_ndk_ManPerson
  5. * Method:    nativeSetup
  6. * Signature: ()V
  7. */
  8. jobject m_obj, p_obj;
  9. jfieldID name_id,age_id,gender_id;
  10. jmethodID pname_mid,page_mid,pgender_mid;
  11. JNIEXPORT void JNICALL Java_com_zuoshaohua_ndk_ManPerson_nativeSetup
  12. (JNIEnv *env, jobject this)
  13. {
  14. #if 1
  15. jclass clz = (*env)->GetObjectClass(env,this);   //通过ManPerson的对象获取ManPerson字节码对象.
  16. m_obj = (*env)->NewGlobalRef(env,this);       //将这个对象设置为全局引用.
  17.  
  18. name_id = (*env)->GetFieldID(env,clz,"name","Ljava/lang/Object;"); //获取ManPerson对象的属性.
  19. age_id = (*env)->GetFieldID(env,clz,"age","I");
  20. gender_id = (*env)->GetFieldID(env,clz,"gender","Ljava/lang/Object;");
  21. jclass personclz = (*env)->FindClass(env,"com/zuoshaohua/ndk/Person"); //通过FindClass方法获取Person类的字节码对象.
  22. jmethodID  constr =(*env)->GetMethodID(env,personclz,"<init>", "()V"); //获取这个对象无参的构造函数.
  23. jobject ref = (*env)->NewObject(env,personclz,constr);           //生成Person对象.
  24. p_obj = (*env)->NewGlobalRef(env, ref);                    //将Person对象设置为全局引用.
  25. pname_mid = (*env)->GetMethodID(env,personclz,"setName","(Ljava/lang/Object;)V"); //获取Person的Setxxx()方法的ID.
  26. page_mid = (*env)->GetMethodID(env,personclz,"setAge", "(I)V");
  27. pgender_mid = (*env)->GetMethodID(env,personclz,"setGender","(Ljava/lang/Object;)V");
  28. #endif
  29. }
  30. /*
  31. * Class:     com_zuoshaohua_ndk_NativeExec
  32. * Method:    nativeExec
  33. * Signature: ()Ljava/lang/Object;
  34. */
  35. JNIEXPORT jobject JNICALL Java_com_zuoshaohua_ndk_NativeExec_nativeExec
  36. (JNIEnv *env, jclass this)
  37. {
  38. #if 1
  39. jint age = 0;
  40. jstring name,gender;
  41. name = (*env)->GetObjectField(env,m_obj,name_id);         //获取ManPerson属性的值.
  42. gender = (*env)->GetObjectField(env,m_obj,gender_id);
  43. age = (*env)->GetIntField(env,m_obj,age_id);
  44. (*env)->CallVoidMethod(env, p_obj,pname_mid,name);    //调用Person的Setxxx()方法给Person对象赋值.
  45. (*env)->CallVoidMethod(env, p_obj,page_mid,age);
  46. (*env)->CallVoidMethod(env, p_obj,pgender_mid,gender);
  47. //(*env)->SetIntField(env,p_obj,age_id,10);         //返回Person对象.
  48. return p_obj;
  49. #endif
  50. }

转载请注明出处: http://blog.csdn.net/shaohuazuo/article/details/42932813

3.3 java反射相关模块

jmethodID (JNICALL *FromReflectedMethod)(JNIEnv *env, jobject method);

jfieldID (JNICALL *FromReflectedField) (JNIEnv *env, jobject field);

jobject (JNICALL *ToReflectedMethod)(JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic);

jobject (JNICALL *ToReflectedField) (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic);

函数背景知识介绍: 请看博客(Java反射机制)  

java.lang.reflect:

提供类和接口,以获得关于类和对象的反射信息。在安全限制内,

反射允许编程访问关于加载类的字段、方法和构造方法的信息,

并允许使用反射字段、方法和构造方法对其底层对等项进行操作。

更多相关知识可以参考http://www.javaweb.cc/help/JavaAPI1.6/

也可以进入博客:?????????????

一:FromReflectedMethod

函数原型: jmethodID (JNICALL *FromReflectedMethod)(JNIEnv *env, jobject method);

 描 述: 通过java.lang.reflect中Method类的对象获取一个函数的MethodID. 就可以调用Java中某个方法.

 参 数: env    java native interface porint,(java本地接口指针)

    method    这个是jva.lang.reflect.Method对象.

要获取Method对象第一步.需要获取Class对象.再通过Class对象获取Method.

1.获取Class对象的三种方法是:

        1.1) 类名.class,例如 Class pclass =  Person.class

        1.2) 对象.getClass(),例如,Class  pclass = new Person().getClass()

        1.3) Class.forName(“类名”),例如,Class pclass = Class.forName(“com.zuoshaohua.Person”);

2.获取Method对象,详细方法介绍可以参考http://www.javaweb.cc/help/JavaAPI1.6/手册

2.1)Class.getMethods(),

2.2)Class.getMethod(String, Class[]),

2.3)Class.getDeclaredMethods(),

     2.4)Class.getDeclaredMethod(String, Class[])

1.5) ToReflectedMethod()通过C中的JNI标准获取Methdod对象.

返回值:返回一个方法的MethodID指针.

二:FromReflectedField

函数原型: jfieldID (JNICALL *FromReflectedField) (JNIEnv *env, jobject field);

 描 述:通过java.lang.reflect中Field类的对象获取字段对象.可以获取这个字段的jfieldID了.

 参 数:  env   java native interface porint,(java本地接口指针)

field   Field对象,这个对象主要用来描述java中的字段信息.通过这个类对象.我们可以获得

          这个字段的名称,类型等等信息.

      1.获取这个对象由如下5种方法:

1.1)Class.getDeclaredField(String name);

返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。

1.2)Class.getDeclaredFields();

返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。

1.3)Class.getField(String name);

返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。

1.4)Class.getField();

返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。 

1.6)ToReflectedFile()

通过C中JNI标准中提供的上面的函数,也可以获取Field对象.

返回值:返回一个字段的jfieldID指针.

三:ToReflectedMethod

函数原型: jobject (JNICALL *ToReflectedMethod)(JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic);

 描 述: 这个方法是通过方法的methodId返回一个java.lang.reflect.Method对象,是FromReflectedMethod的反操作.

参 数: env      java native interface porint,(java本地接口指针)

cls       该方法的类对象.可以通过FindClass()获取.如果知道对象的话可以使用GetObjectClass()来获取这个jclass对象.

methodID       这个对象是jmethodID指针.可以通过GetMethodID方法获取.

 isStatic     该方法是不是静态的,JNI标准中提供了两个宏表示.JNI_FALSE,和JNI_TRUE.

返回值:返回一个Method对象.也就是说再FromReflectedMethod 中多了一种方法可以获取Method对象的方法.

四:ToReflectedField

函数原型: jobject (JNICALL *ToReflectedField) (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic);

 描 述: 通过filedID可以返回一个java.lang.reflect.Field对象.

 参 数: env java native interface porint,(java本地接口指针)

cls  该方法的类对象.可以通过FindClass()获取.如果知道对象的话可以使用GetObjectClass()来获取这个jclass对象.

methodID  这个对象是jField指针.可以通过GetFieldID方法获取.

isStatic  该方法是不是静态的,JNI标准中提供了两个宏表示.JNI_FALSE,和JNI_TRUE.

返回值: 返回一个Field对象.

五:例程

  1.1 流程     

   1. 定义一个Person类.这个Person类三个属性.name, age, gender.还有getxxx()和setxxx()方法.

2. 定义一个Android的界面.它的MainActivity类关联了一个Person对象.也就是,Person类是Activity的一个属性.

3. 在MainActivity中,静态初始化这个Person对象.我们使用该静态对象.p.getClass()获取类Class对象clz. 

4. 我们需要获取这个Class中的Method对象和Field对象.clz.getMethod(); clz.getField对象.

     通过 ReflectMethodDeom本地方法和ReflectFieldDemo本地方法传入到C层.

   5. c通过这两个对象获取到对象的jfieldID对象和jmethodID.并进行相应的操作.

  1.2    类图

  1.3   代码  

   1. MainActivity代码

  1. package com.zuoshaohua.reflect;
  2. import java.lang.reflect.Field;
  3. import java.lang.reflect.InvocationTargetException;
  4. import java.lang.reflect.Method;
  5. import android.os.Bundle;
  6. import android.app.Activity;
  7. import android.view.Menu;
  8. import android.view.View;
  9. import android.view.View.OnClickListener;
  10. import android.widget.Button;
  11. import android.widget.TextView;
  12. public class MainActivity extends Activity implements OnClickListener {
  13. private static Person  p = new Person("zuoshaohua",33,"男");
  14. private Button runBtn;
  15. private Button exitBtn;
  16. TextView textView;
  17. static {
  18. System.loadLibrary("reflect");
  19. }
  20. @Override
  21. protected void onCreate(Bundle savedInstanceState) {
  22. super.onCreate(savedInstanceState);
  23. setContentView(R.layout.activity_main);
  24. runBtn  = (Button)this.findViewById(R.id.run);
  25. exitBtn = (Button)this.findViewById(R.id.exit);
  26. textView = (TextView)this.findViewById(R.id.personView);
  27. this.runBtn.setOnClickListener(this);
  28. this.exitBtn.setOnClickListener(this);
  29. }
  30. private void refelectTest(){
  31. Class<? extends Person> c =  p.getClass();
  32. try {
  33. StringBuffer sb = new StringBuffer();
  34. Method method = c.getMethod("setAge", int.class);
  35. //Field field = c.getField("age");
  36. Field field = c.getDeclaredField("age");
  37. sb.append("oldName ="+p.getName()+"oldAge="+p.getAge()+ "oldGender="+p.getGender()+"\n");
  38. Field field1 = ReflectFieldDemo(p,field);   //调用本地方法.将描述age字段的Field对象传进去.
  39. //field1.set(p, "shaohuazuo");
  40. Method m1 = ReflectMethodDemo(p,method);    //调用本地方法.将描述setAge()方法的Method对象传入到C层代码.
  41. sb.append("oldName1 ="+p.getName()+"oldAge1="+p.getAge()+ "oldGender1="+p.getGender()+"\n");
  42. Object args[] = new Object[1];
  43. args[0] = new  String("shaohuazuo");
  44. m1.invoke(p, args);                         //调用返回的方法.
  45. field1.setAccessible(true);
  46. String name =(String)field1.get(p);
  47. sb.append("newName ="+name+"newAge="+p.getAge()+"newGender="+p.getGender());
  48. textView.setText(sb.toString());
  49. } catch (NoSuchMethodException e) {
  50. e.printStackTrace();
  51. } catch (NoSuchFieldException e) {
  52. // TODO Auto-generated catch block
  53. e.printStackTrace();
  54. } catch (IllegalAccessException e) {
  55. // TODO Auto-generated catch block
  56. e.printStackTrace();
  57. } catch (IllegalArgumentException e) {
  58. // TODO Auto-generated catch block
  59. e.printStackTrace();
  60. } catch (InvocationTargetException e) {
  61. // TODO Auto-generated catch block
  62. e.printStackTrace();
  63. }
  64. }
  65. @Override
  66. public boolean onCreateOptionsMenu(Menu menu) {
  67. // Inflate the menu; this adds items to the action bar if it is present.
  68. getMenuInflater().inflate(R.menu.main, menu);
  69. return true;
  70. }
  71. private  static native Field ReflectFieldDemo(Person p,Field f);
  72. private  static native Method ReflectMethodDemo(Person p, Method m);
  73. @Override
  74. public void onClick(View arg0) {
  75. // TODO Auto-generated method stub
  76. switch(arg0.getId())
  77. {
  78. case R.id.run:
  79. refelectTest();
  80. break;
  81. case R.id.exit:
  82. this.finish();
  83. break;
  84. default:
  85. this.finish();
  86. break;
  87. }
  88. }
  89. }

2. Person.java代码

  1. package com.zuoshaohua.reflect;
  2. public class Person {
  3. private String name;
  4. private int age;
  5. private String gender;
  6. public Person(String string, int age, String gender) {
  7. this.name = name;
  8. this.age = age;
  9. this.gender = gender;
  10. }
  11. public String getName() {
  12. return name;
  13. }
  14. public void setName(String name) {
  15. this.name = name;
  16. }
  17. public int getAge() {
  18. return age;
  19. }
  20. public void setAge(int age) {
  21. this.age = age;
  22. }
  23. public String getGender() {
  24. return gender;
  25. }
  26. public void setGender(String gender) {
  27. this.gender = gender;
  28. }
  29. }

3. 生成.h头文件.

zshh@HP:~/work/android/jni/Reflect/jni$

javah -o reflect.h -classpath ../bin/classes com.zuoshaohua.reflect.MainActivity

4. reflect.h代码

  1. /* DO NOT EDIT THIS FILE - it is machine generated */
  2. #include <jni.h>
  3. /* Header for class com_zuoshaohua_reflect_MainActivity */
  4. #ifndef _Included_com_zuoshaohua_reflect_MainActivity
  5. #define _Included_com_zuoshaohua_reflect_MainActivity
  6. #ifdef __cplusplus
  7. extern "C" {
  8. #endif
  9. /*
  10. * Class:     com_zuoshaohua_reflect_MainActivity
  11. * Method:    ReflectFieldDemo
  12. * Signature: (Lcom/zuoshaohua/reflect/Person;Ljava/lang/reflect/Field;)Ljava/lang/reflect/Field;
  13. */
  14. JNIEXPORT jobject JNICALL Java_com_zuoshaohua_reflect_MainActivity_ReflectFieldDemo
  15. (JNIEnv *, jclass, jobject, jobject);
  16. /*
  17. * Class:     com_zuoshaohua_reflect_MainActivity
  18. * Method:    ReflectMethodDemo
  19. * Signature: (Lcom/zuoshaohua/reflect/Person;Ljava/lang/reflect/Method;)Ljava/lang/reflect/Method;
  20. */
  21. JNIEXPORT jobject JNICALL Java_com_zuoshaohua_reflect_MainActivity_ReflectMethodDemo
  22. (JNIEnv *, jclass, jobject, jobject);
  23. #ifdef __cplusplus
  24. }
  25. #endif
  26. #endif

5. reflect.c代码

  1. #include "reflect.h"
  2. #include <android/log.h>
  3. #include <stdio.h>
  4. #if 0
  5. jmethodID (JNICALL *FromReflectedMethod) (JNIEnv *env, jobject method);
  6. jfieldID (JNICALL *FromReflectedField) (JNIEnv *env, jobject field);
  7. jobject (JNICALL *ToReflectedMethod) (JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic);
  8. jobject (JNICALL *ToReflectedField) (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic);
  9. #endif
  10. jclass clazz;
  11. /*
  12. * Class:     com_zuoshaohua_reflect_MainActivity
  13. * Method:    ReflectFieldDemo
  14. * Signature: (Lcom/zuoshaohua/reflect/Person;Ljava/lang/reflect/Field;)Ljava/lang/reflect/Field;
  15. */
  16. JNIEXPORT jobject JNICALL Java_com_zuoshaohua_reflect_MainActivity_ReflectFieldDemo
  17. (JNIEnv * env, jclass this, jobject pthis, jobject fthis)
  18. {
  19. jint age =0;
  20. jclass clz =(*env)->GetObjectClass(env,pthis);     //通过Person对象获取他的Class对象信息,从而得到一个jclass对象.
  21. jfieldID age_id = (*env)->FromReflectedField(env,fthis); //通过Field对象获取Person属性的jfieldID指针.
  22. age = (*env)->GetIntField(env,pthis,age_id);               //通过这个对象和age_id获取这个属性的值.
  23. __android_log_print(ANDROID_LOG_INFO, "ReFlectFieldDemo", "age: %d", age);
  24. jfieldID name_id = (*env)->GetFieldID(env,clz,"name","Ljava/lang/String;");  //获取name字段的jfieldID.
  25. __android_log_print(ANDROID_LOG_INFO, "ReFlectFieldDemo", "end!!!!!");
  26. return (*env)->ToReflectedField(env,clz,name_id,JNI_FALSE);    //通过jfieldID生成一个Java的Field对象.并返回.
  27. }
  28. /*
  29. * Class:     com_zuoshaohua_reflect_MainActivity
  30. * Method:    ReflectMethodDemo
  31. * Signature: (Lcom/zuoshaohua/reflect/Person;Ljava/lang/reflect/Method;)Ljava/lang/reflect/Method;
  32. */
  33. JNIEXPORT jobject JNICALL Java_com_zuoshaohua_reflect_MainActivity_ReflectMethodDemo
  34. (JNIEnv *env , jclass this, jobject pthis, jobject mthis)
  35. {
  36. //我们使用mthis.来获取jmethodID指针.并通过该指针调用到set方法.来改变Person属性的值.
  37. jclass pclazz = (*env)->GetObjectClass(env,pthis);
  38. jmethodID setAgeId = (*env)->FromReflectedMethod(env,mthis);
  39. (*env) ->CallVoidMethod(env,pthis,setAgeId,100);
  40. __android_log_print(ANDROID_LOG_INFO,"ReflectMethodDemo","is callVoidMethod Done!!!!\n");
  41. jmethodID setName_id = (*env)->GetMethodID(env,pclazz,"setName","(Ljava/lang/String;)V");
  42. return (*env)->ToReflectedMethod(env, pclazz,setName_id, JNI_FALSE);
  43. }

6. Android.mk代码

  1. SRC_PATH_ROOT:=$(LOCAL_PATH)/../../src
  2. LOCAL_PATH := $(call my-dir)
  3. include $(CLEAR_VARS)
  4. LOCAL_MODULE    := reflect
  5. LOCAL_SRC_FILES := reflect.c
  6. LOCAL_LDLIBS := -llog
  7. #LOCAL_SHARED_LIBRARIES :=libc
  8. include $(BUILD_SHARED_LIBRARY)
  1.4  测试结果

jni.h头文件详解二的更多相关文章

  1. 【转】 jni.h头文件详解(二)

    原文网址:http://blog.csdn.net/shaohuazuo/article/details/42932813 作者:左少华 博客:http://blog.csdn.net/shaohua ...

  2. jni.h头文件详解一

    1.jni.h头文件路径: /usr/lib/jvm/jdk_1.6.0_43/include/jni.h 2.jni.h头文件组成分析图: 3.下面通过上图进行分析讲解jni.h头文件. 一. jn ...

  3. linux内核中链表代码分析---list.h头文件分析(二)【转】

    转自:http://blog.chinaunix.net/uid-30254565-id-5637598.html linux内核中链表代码分析---list.h头文件分析(二) 16年2月28日16 ...

  4. Linux 头文件详解

    概览: 头文件目录中总共有32个.h头文件.其中主目录下有13个,asm子目录中有4个,Linux子目录中有10个,sys子目录中有5个. <a.out.h>:a.out头文件,定义了a. ...

  5. javascript —— HTTP头文件详解

    HTTP(超文本传输协议:HyperText Transfer Protocol)是浏览器和服务器通过internet进行相互通信的协议,也是网络上应用最为广泛的一种网络协议.HTTP规范由World ...

  6. PE文件详解二

    本文转自小甲鱼的PE文件相关教程,原文传送门 咱接着往下讲解IMAGE_OPTIONAL_HEADER32 结构定义即各个属性的作用! 接着我们来谈谈 IMAGE_OPTIONAL_HEADER 结构 ...

  7. http请求头、响应头文件详解

    HTTP Request Header 请求头   解释 示例 Accept 指定客户端能够接收的内容类型 Accept: text/plain, text/html Accept-Charset 浏 ...

  8. MyBatis之Mapper XML 文件详解(二)-sql和入参

    sql 这个元素可以被用来定义可重用的 SQL 代码段,可以包含在其他语句中.它可以被静态地(在加载参数) 参数化. 不同的属性值通过包含的实例变化. 比如: <sql id="use ...

  9. [转]文件IO详解(二)---文件描述符(fd)和inode号的关系

    原文:https://www.cnblogs.com/frank-yxs/p/5925563.html 文件IO详解(二)---文件描述符(fd)和inode号的关系 ---------------- ...

随机推荐

  1. 接收Firfox RESTClient #Post请求

    什么是 RESTClient 请参考:http://www.blogjava.net/paulwong/archive/2014/04/19/412688.html 对接接口时经常会需要传个异步回调消 ...

  2. 怎样向IT行业的朋友说明《圣经》的重要性

    “世界的官方文档”——怎么样?

  3. iOS UIView 快速修改 frame,

    在iOS开发布局修改 frame 时需要繁琐的代码实现,今天偶尔看到一播客说到快速修改的 frame 的方法,自己动手写了一遍实现代码. 快速实现主要通过 添加类目的方式,对UIView 控件添加了一 ...

  4. iOS启动图片适配问题

    Portrait 是竖屏 top home button Landscape是横屏 left home button retina 要求640x1136pixels, 在右边的Image属性 Expe ...

  5. Microsoft Excel Sheet/表格 制作折线图

    Microsoft Excel Sheet/表格 制作折线图 虽然比较简单,但是仍然需要稍微花一点功夫. 1.制作好表格数据 2.先将数据选定(不包括 横座标的 年月日或其他的刻度 的那一列) 3.插 ...

  6. json字符串转JSONObject,输出JSONObject问题

    json架包:json-lib-2.4-jdk15.jar json字符串(存在null值)转JSONObject 后return JSONObject对象的时候会报错 例如: String str= ...

  7. SSH+Ajax实现用户名重复检查(二)

    1.另外一种更常用的js表达方式: var user = { inintEvent: function(){ $("input[name='user.User_LogName']" ...

  8. Git问题:Cannot update paths and switch to branch 'dev' at the same time.

    使用命令 $ git checkout -b develop origin/develop 签出远程分支,出现以下错误: fatal: Cannot update paths and switch t ...

  9. mysql中的load命令使用方法

    使用mysql 中的load 命令,可以将txt 文件中的内容加载到数据库表中 使用mysql 中的load 命令,讲txt 文件中的内容加载到数据库表中,例如,创建table,名称是user,一个字 ...

  10. GPU CUDA常量内存使用

    #include <cuda.h> #include <stdio.h> int getMulprocessorCount(){ cudaDeviceProp prop; cu ...