<strong>
</strong>
本章讲解so层怎么修改java层的变量,以及so层调用java层的方法,直接上代码.
package JNIEnvMethod;

public class JniDemo {

	static {
		System.load(
				"F:\\HelloJava_Code_AndroidDecompilation\\_(一)Decompilation_testJNI\\libs\\lib_(一)JNIEnvMethods.dll");
	}

	String name = "~~";
	String sex = "~~";
	String age = "~~";

	//
	public static void main(String[] args) {
		JniDemo mJniDemo = new JniDemo();
		mJniDemo.BxlCPPMethod("My decompilation");
		System.out.println("name:" + mJniDemo.name + "; sex:" + mJniDemo.sex + "; age:" + mJniDemo.age);
		mJniDemo.awaitSoInvoke("java");
	}

	native void BxlCPPMethod(String jstr);

	public void awaitSoInvoke(String param1) {
		System.out.println(String.format("我被%s运行了", param1));
	}
}

c++代码:

#include "jni.h"
//#include <string>
#include "JNIEnvMethod_JniDemo.h"

/** 本章解析:
 *
 * 本章内存比较简单,主要是说的
 * 	1.java字符串怎么转c++字符串
 * 	2.c++访问java层的全局变量
 * 	3.c++调用java层的方法
 *
 * 	主要牵涉的方法有:
 * 	Get***ID:获取方法 / 变量ID(需要对应的clazz/名字/签名)
 * 	getObjectClass:其实也可以这样写:env->FindClass("JNIEnvMethod.JniDemo"); 其实就是一个反射!
 * 	Call**Method: 调用java层方法
 *
 * 	jclass: 可以想成是java里面的反射, 通过他可以获取到该类里面所有的成员变量/方法, 但是不能对该变量/方法做任何的操作!为什么?因为你没有对象!没有实例!而方法的对象是谁?是jobject!
 * 	jobject: 上面其实已经说了,jobject是java层的对象,谁调用谁对象!通过getobjectclass/findclass可获取到jclass,在结合jobject是不是就可以对参数对象实现调用 修改了?
 *
 *  方法签名:什么是方法签名?这么说吧,这个东西不用理解,死记就行,看多了就记住了.如果逆向过apk,应该就很好记,smail语法随处可见这东西
 *  		打个几个比方来说:(Ljava/lang/String;)V : 括号里面的"Ljava/lang/String;"说明方法的有一个参数String, "V"说明方法的返回值是void
 *  					   (Ljava/lang/String;)Ljava/lang/String; : 括号里面的"Ljava/lang/String;"说明方法的有一个参数String, "V"说明方法的返回值是String
 *			可以这么想,方法签名就是 方法参数和方法返回值的一组特殊字符串,参数签名就是参数的类型!
 *	签名对应表:boolean : Z
 *	 	 	 char : c
 *	 	 	 byte : B
 *	 	 	 short : S
 *	 	 	 int : I
 *	 	 	 long : J
 *	 	 	 float : F
 *	 	 	 double : D
 *
 *
 */

/**
 * 参数一:env 代表的是java环境!,可以想成是一个数组,里面装的全是方法,
 * 参数二:obj 代表的是java层调用者的对象,谁调用的这个so,obj就代表谁的对象
 * 参数三:jstr代表的是java层第一个参数
 * 参数四:这里其实是没有参数四的. 如果有,它代表的是java层的第二个参数.
 * 参数五:同上!
 */
JNIEXPORT void JNICALL Java_JNIEnvMethod_JniDemo_BxlCPPMethod(JNIEnv *env,
		jobject obj, jstring jstr) {

	/** 一:GetStringUTFChars方法:jstr转cstr并输出
	 *
	 */
	jsize jstrLength = env->GetStringLength(jstr);
	const char *cstr = env->GetStringUTFChars(jstr, NULL);
	printf("str:%s; length:%ld", cstr, jstrLength);

	/** 二:获取java的全局变量并修改
	 *
	 * GetObjectClass:类似getClass();
	 * getXXXID类方法:此类方法可以获取java层的信息(全局变量 方法),其中参数三是字段签名,签名在最后讲;可以想成放射获取
	 */
	//修改字段name的值为caijincheng
	jfieldID name = env->GetFieldID(env->GetObjectClass(obj), "name",
			"Ljava/lang/String;");
	char new_name[40] = "CaiJinCheng";
	jstring nameValue = env->NewStringUTF(new_name);
	env->SetObjectField(obj, name, nameValue);

	//修改sex的字段为N
	jfieldID sex = env->GetFieldID(env->GetObjectClass(obj), "sex",
			"Ljava/lang/String;");
	char new_sex[40] = "N";
	jstring sexValue = env->NewStringUTF(new_sex);
	env->SetObjectField(obj, sex, sexValue);

	//设置age的字段为26
	jfieldID age = env->GetFieldID(env->GetObjectClass(obj), "age",
			"Ljava/lang/String;");
	char new_age[40] = "26";
	jstring ageValue = env->NewStringUTF(new_age);
	env->SetObjectField(obj, age, ageValue);

	/** 三.获取java层方法,并调用
	 *
	 * GetMethodID: 通过方法class/方法名/方法签名来获取java层方法的id.
	 * CallVoidMethod:通过方法id 和 class对象来调用java层的方法;
	 */
	jmethodID jawaitSoInvoke = env->GetMethodID(env->GetObjectClass(obj),
			"awaitSoInvoke", "(Ljava/lang/String;)V");
	char new_param[] = "c++";
	jstring param1 = env->NewStringUTF(new_param);
	env->CallVoidMethod(obj, jawaitSoInvoke, param1);

}



为了方便.上面的代码并没有在android环境上写,而是用的java环境,其实是一样的,或者说一模一样.