【参考链接】
程序运行时,以主线程的main()方法为入口,不停的从一个方法调用到另一个方法中,方法返回再继续调用其他的
根据之前JVM的知识,其实就是在不停向栈中压入栈帧、弹出栈帧
所以既可以在java方法中调用C/C++方法,也可以在C/C++方法中调用Java方法,只不过这两种栈是分开维护的。
Java方法到C/C++方法
给一个类定义一个native方法,实现其对应的C/C++方法,在Java中调用这个native方法就会去调用C/C++方法
这个native方法可以是非static的,其对应方法的前两个参数的类型为JNIEnv,jobject,
也可以是static的,其对应方法的前两个参数的类型为JNIEnv,jclass
这些类型都是在jni.h中定义的,其中
JNIEnv,其在C中的定义为结构体JNINativeInterface的指针,后续主要就是使用这个类型中的各种函数指针(指向函数的指针)
jobject,代表调用的这个Java对象,jclass,代表调用的这个Java类,如果在C/C++中要使用的正是这个对象/这个类,则不用去重新获取。
C/C++方法到Java方法
在C/++方法中调用Java方法,代码跟反射有点像,需要先获取到这个方法,然后再调用这个方法。
获取方法主要通过JNIEnv的如下方法
需要知道这个方法的描述符,这在Class文件结构中已讲过,此外还可以通过先编译然后执行javap –s指令得到
调用方法主要通过JNIEnv的如下方法
以如下代码为例
先从Java方法中调用到C方法nativeMethod1,然后再去调用Java类Test1的某个新建对象的非静态方法test();
先从Java方法中调用到C方法nativeMethod2,然后再去调用Java类Test2的静态方法test();
public class MainActivity extends Activity {
public nativevoid nativeMethod1();
public static native void nativeMothod2();
@Override
protected void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.loadLibrary("testtt");
}
public void onClick1(View view){
nativeMethod1();
}
public void onClick2(View view){
nativeMothod2();
}
}
#include "com_example_shadowfaxghh_demo_MainActivity.h"
JNIEXPORT void JNICALL Java_com_example_shadowfaxghh_demo_MainActivity_nativeMethod1
(JNIEnv *env, jobject jobj) {
//调用Test1的成员方法test()
//获取到类
jclass clazz=(*env)->FindClass(env, "com/example/shadowfaxghh/demo/Test1");
//获取到方法//GetMethodID
jmethodID methodID=(*env)->GetMethodID(env, clazz, "test", "()V");
//创建对象
jobject jobj2=(*env)->AllocObject(env, clazz);
//调用方法//CallVoidMethod
(*env)->CallVoidMethod(env, jobj2, methodID);
}
JNIEXPORT void JNICALL Java_com_example_shadowfaxghh_demo_MainActivity_nativeMothod2
(JNIEnv *env, jclass jclazz) {
//调用Test2的成员方法test()//静态
//获取到类
jclass clazz=(*env)->FindClass(env, "com/example/shadowfaxghh/demo/Test2");
//获取到方法//GetStaticMethodID
jmethodID methodID=(*env)->GetStaticMethodID(env, clazz, "test", "()V");
//调用方法//CallStaticVoidMethod
(*env)->CallStaticVoidMethod(env, clazz, methodID);
}