JNI类型签名和方法签名

1,150 阅读2分钟

简介

最近在研究Flutter Engine,里面涉及到JNI的知识,笔记记录一下关于JNI类型签名和方法签名。

数据类型

基本数据类型

Java数据类型JNI本地类型C/C++数据类型描述说明
booleanjbooleanunsigned charC/C++无符号8为整数
bytejbytesigned charC/C++有符号8为整数
charjcharunsigned shortC/C++无符号16位整数
shortjshortsigned shortC/C++有符号16位整数
intjintsigned intC/C++有符号32位整数
longjlongsigned longC/C++有符号64位整数
floatjfloatfloatC/C++32位浮点数 
doublejdoubledoubleC/C++64位浮点数

引用数据类型

Java引用类型JNI引用类型描述说明
java.lang.Objectjboject可以表示任何Java的对象,或者没有JNI对应类型的Java对象(实例方法的强制参数
java.lang.StringjstringJava的String字符串类型的对象
java.lang.ClassjclassJava的Class类型对象(静态方法的强制参数)
Object[]jobjectArrayJava任何对象的数组表示形式
boolean[]jbooleanArrayJava基本类型boolean的数组表示形式
byte[]jbyteArrayJava基本类型byte的数组表示形式
char[]jcharArrayJava基本类型char的数组表示形式
short[]jshortArrayJava基本类型short的数组表示形式
int[]jintArrayJava基本类型int的数组表示形式
long[]jlongArrayJava基本类型long的数组表示形式
float[]jfloatArrayJava基本类型float的数组表示形式
double[]jdoubleArrayJava基本类型double的数组表示形式
java.lang.ThrowablejthrowableJava的Throwable类型,表示异常的所有类型和子类
voidvoidN/A

数据类型描述符

数据类型描述符解释

在JVM虚拟机中,存储数据类型的名称时,是使用指定的描述符来存储,而不是我们习惯的 int,float 等

数据类型描述符对照表

Java类型描述符类型
intI
longJ
byteB
shortS
charC
floatF
doubleD
booleanZ
voidV
引用类型L+类全名+;
数组[
方法(参数)返回值

示例

flutter注册代码

bool FlutterMain::Register(JNIEnv* env) {
  static const JNINativeMethod methods[] = {
      {
          .name = "nativeInit",
          .signature = "(Landroid/content/Context;[Ljava/lang/String;Ljava/"
                       "lang/String;Ljava/lang/String;Ljava/lang/String;J)V",
          .fnPtr = reinterpret_cast<void*>(&Init),
      },
      {
          .name = "nativePrefetchDefaultFontManager",
          .signature = "()V",
          .fnPtr = reinterpret_cast<void*>(&PrefetchDefaultFontManager),
      },
  };

  jclass clazz = env->FindClass("io/flutter/embedding/engine/FlutterJNI");

  if (clazz == nullptr) {
    return false;
  }

  return env->RegisterNatives(clazz, methods, fml::size(methods)) == 0;
}

} 

还原nativeInit在java中的方法声明

"(Landroid/content/Context;[Ljava/lang/String;
    Ljava/lang/String;
    Ljava/lang/String;
    Ljava/lang/String;
    J)V"
public void  nativeInit(Context context,
    String[] args,
    String s1,
    String s2,
    String s3,
    long l);

实际情况

  private static native void nativeInit(
      @NonNull Context context,
      @NonNull String[] args,
      @Nullable String bundlePath,
      @NonNull String appStoragePath,
      @NonNull String engineCachesPath,
      long initTimeMillis);