so层获取Java层的字段和静态字段

一、编写java代码
  1.java代码定义字段名称以及类型,一个静态一个非静态
    //普通字段
    public String  testStr = "java普通字段";
    //静态字段
    public static String  staticTtestStr = "java静态字段";

0.png


二、使用javah生成c的头部文件
  1.生成头文件,来到java的源码目录,ADT下来到src目录,AndroidStudio来到蓝色文件夹目录即java执行以下命令:
//javah 包名+类名,会自动生成.h文件包含类里面的所有被native修饰的方法
javah com.example.mypc.myxphook.MainActivity
  2.如果报以下错误(错误: 编码GBK的不可映射字符)可尝试加入参数:

1.png

//javah -encoding UTF-8 包名加类名
javah -encoding UTF-8 com.example.mypc.myxphook.MainActivity

2.png


  4.重命名.h文件并移动到src同级的jni目录(我这里重命名testJni.h)并创建.c文件

3.png


三、编写c代码

  1.默认创建完的文件是空的,需要引入javah生成的.h文件改名后再头部使用#includ引入,然后把头文件内的方法复制过来,尾部的分号删除,加上花括号{}然后在花括号内写实现代码,这里简单实现获取java层的字段内容

4.png


  2.编写c代码引入头文件,复制方法到c文件内,开始编写实现代码.方法最后返回的是一个jobject类型的数据,但是不影响在java内接收.
   2.1 获取普通字段内容

5.png


   2.2获取静态字段内容

6.png



友情提示:编写代码的时候从我们最终的目的逆向编写代码,先获取字段,然后在获取字段所需的参数比如jclass,jfieldID,等...

四、附上c的最终代码,以及运行结果

  1.c文件代码如下:

//
// Created by MyPC on 2020/4/14.
//
#include "testJni.h"

//获取JAVA层普通字段值内容,编写顺序从下至上(缺啥找啥)
JNIEXPORT jstring JNICALL Java_com_example_mypc_myxphook_MainActivity_getTestStr
  (JNIEnv *env, jobject obj){


    //查找Java的Class类返回一个jclass,env  第二个参数为类的路径
    //JNI原方法    jclass      (*FindClass)(JNIEnv*, const char*);
    jclass   clazz = (*env)->FindClass(env,"com/example/mypc/myxphook/MainActivity");

    //env,obj,字段变量名称,签名也就是类型,L标识类类型,尾部加分号;
    //JNI原方法    jfieldID    (*GetFieldID)(JNIEnv*, jclass, const char*, const char*);
    jfieldID jfieldId = (*env)->GetFieldID(env,clazz,"testStr","Ljava/lang/String;");

    //获取字段 env,obj,字段id
    //JNI原方法    jobject     (*GetObjectField)(JNIEnv*, jobject, jfieldID);
    jobject str = (*env)->GetObjectField(env,obj,jfieldId);

    //返回字符串
    return str;

}

//获取java层静态字段值内容
JNIEXPORT jstring JNICALL Java_com_example_mypc_myxphook_MainActivity_getStaticTestStr
  (JNIEnv *env, jobject obj){

    //查找Java的Class类返回一个jclass,env  第二个参数为类的路径
    //JNI原方法    jclass      (*FindClass)(JNIEnv*, const char*);
    jclass   clazz = (*env)->FindClass(env,"com/example/mypc/myxphook/MainActivity");

    //获取静态字段ID  env,obj,字段变量名称,签名也就是类型,L标识类类型,尾部加分号;
    //JNI 原方法   jfieldID    (*GetStaticFieldID)(JNIEnv*, jclass, const char*, const char*);
    jfieldID   jfieldId =  (*env)->GetStaticFieldID(env, clazz, "staticTtestStr", "Ljava/lang/String;");

    //获取静态字段值内容
    //JNI原方法    jobject     (*GetStaticObjectField)(JNIEnv*, jclass, jfieldID);
    jobject staticStr = (*env)->GetStaticObjectField(env, clazz, jfieldId);

    return staticStr;
}

  2.编译(如果使用AndroidStudio配置了jni目录就不需要运行ndk-build否则会报错)打包运行结果如下:

7.png

8.png


在浏览的同时希望给予作者打赏,来支持作者的服务器维护费用.一分也是爱~