1、首先,需要在类中定义静态调用本地化语言(.dll,.so)库

如下:

static {
         System.loadLibrary("Jniclass");
     }


2、再以native方法申明某函数调用原生库中的函数:

public static native String momo_say_Hello(String name);


3、接下来在JAVA中就可以像调用JAVA语言类中静态函数的方法调用该函数:

public static void main(String []arg)
  {

   momo_say_Hello("hello world!");
   
  }


4、之后使用javac命令编译class文件

javac xxx.java

使用javah创建jni中C语言头文件,javah是对.class文件进行分析的,且不需要后缀

javah xxx

当然,创建C语言头文件也可以自己手动写,需要注意的是,jni是通过标准格式函数名来加载接口函数的

格式规范如下:

JAVA_(类名)_(JAVA中接口函数名)(参数1,参数2,……)

基本类型使用jni中的参数映射的对象,类对象使用object;见数据类型对照表

字符串较特殊,因为JAVA中没有指针,C中字符串实际上是字符指针,需要转换为jstring

数组也是比较特殊的,因为JAVA中数组属于内置类型,而C中的数组仍本质然是指针,需要转换成各种 _jXXXarray


需要注意的一点是,JAVA是面向对象编程的语言,所有内容都是类以及类的成员,JNI是搞JAVA的人搞出来的,思路当然更接近JAVA一些

既然所有函数(方法)都是类里面的对象,JNI中的导入函数当然不例外,该函数是这个类中的对象,不能被其他类直接引用

所以,接口命名规则就包含了,类名与方法名,然后最前面的JAVA表明身份是用于JNI的导出函数

很明显的可以看出,JNI是通过“_”(下划线)来区分JAVA关键字,类名关键字,函数(方法)名关键字的

那么,问题来了,如果类名中如果有个"_",如my_hello,方法名也有个"_"如momo_say_Hello( String name),

那么直接在原生语言中组合出一个JAVA_my_hello_momo_say_Hello函数

JNI会认为他是:

1、my类中的hello_momo_say_Hello函数

2、my_hello类中的momo_say_Hello函数

3、my_hello_momo类中的say_Hello函数

4、my_hello_momo_say类中的Hello函数

这样岂不是搞混了,所以,对于有"_"的函数和类,统统将"_"变成"_1"

实际上就相当于一个转译符

最终原生语言中的JNI导出函数为:JAVA_my_1hello_momo_1say_1Hello


附录,数据类型对照表:

JAVA类型

本地类型

JNI中自定义类型

描述

int

long

jint/jsize

signed 32 bits

long

_int64

jlong

signed 64 bits

byte

signed char

jbyte

signed 8 bits

boolean

unsigned char

jboolean

unsigned 8 bits

char

unsigned short

jchar

unsigned 16 bits

short

short

jshort

signed 16 bits

float

float

jfloat

32 bits

double

double

jdouble

64 bits

void

void

void

N/A