Skip to content

Latest commit

 

History

History
107 lines (71 loc) · 3.13 KB

2.1.md

File metadata and controls

107 lines (71 loc) · 3.13 KB

Java、JNI交互

一、Java调用JNI方法

其实在AS帮助我们创建的工程里,就已经向我们阐述了java如何调用native方法。

1、加载so库,选择合适的时机加载需要使用的so库,例如在静态代码块中直接加载。

// Used to load the 'native-lib' library on application startup.
static {
    System.loadLibrary("native-lib");
}

2、调用Java中通过native声明的方法,最终会调用到native中的C/C++代码。

二、JNI调用Java实例方法
public void sayHello() {
    Log.d(TAG, "Hello I am Java method.");
}
extern "C" 
JNIEXPORT void JNICALL
Java_com_jdqm_ndktutorials_MainActivity_callJavaMethod(JNIEnv *env, jobject thiz) {
    jclass jclazz = env->FindClass("com/jdqm/ndktutorials/MainActivity");
    jmethodID jmethodId = env->GetMethodID(jclazz, "sayHello", "()V");
    env->CallVoidMethod(thiz, jmethodId);
}

这个例子是在native层调用了Java的实例方法seyHello(),分3步:

  • 找到jclass;
  • 找到jclass中对应的方法id;
  • 调用方法
三、JNI调用Java静态方法
public static void staticSayHello() {
    Log.d(TAG, "Hello I am Java static method.");
}
extern "C"
JNIEXPORT void JNICALL
Java_com_jdqm_ndktutorials_MainActivity_callJavaStaticMethod(JNIEnv *env, jclass clazz) {
    jclass jclazz = env->FindClass("com/jdqm/ndktutorials/MainActivity");
    jmethodID jmethodId = env->GetStaticMethodID(jclazz, "staticSayHello", "()V");
    env->CallStaticVoidMethod(jclazz, jmethodId);
}

步骤其实和实例方法差不多,只不过调用env中的方法时,多了Static。值得一提的是,静态native方法JNIEnv *env, jclass clazz第二个参数是jclass,对应的是声明native方法的Class对象,而实例方法则是jobject,对应的是声明native方法类的实例对象。

留意其中一个函数

jmethodID GetStaticMethodID(jclass clazz, const char* name, const char* sig)

这个函数的三个参数分别是:Class对象,方法名,方法签名。其中方法签名是用来辅助找到方法,因为Java中方法可以重载,也就是说单单通过方法名无法定位到具体的方法。这里的方法签名包含两个部分:参数列表,返回值,早期可以用命令javap来辅助查看方法签名,熟悉规律了之后其实就不在需要了。

javap

JNI方法签名规范

基本格式

(参数1类型;参数2类型;...参数N;)返回值类型

当参数为引用类型的时候,参数类型的根式为"L包名",其中包名的.(点)要换成"/",比如String是Ljava/lang/String,Bundle是(Landroid/os/Bundle。

Java类型 类型标识
boolean Z
byte B
char C
short S
int I
long J
float F
double D

这个其实很好记的,除了boolean和long,其他都是首字母大写,主要这两个被占用了,B被byte占用,L与引用类型“L包名”冲突。如果返回值是void,对应的签名是V。另外有一个特殊的类型:数组

Java类型 类型标识
int[] [I
String[] [Ljava/lang/String;