JNI学习开始篇 基础知识 数据映射及学习资料收集
JNI介绍
JNI(Java Native Interface) ,Java本地接口。
用Java去调用其他语言编写的程序,比如C或C++。
JNI作为二者连接的桥梁。
Java的跨平台本质主要是由于JVM不是跨平台的,JNI本身也不是跨平台的,即JNI是与特定平台相关的。
本地方法调用
native关键字:使用native所修饰的方法为本地方法,该方法只有声明,没有实现,表示该实现是由C/C++来提供的。
JNI本质上就是Java代码调用动态链接库的过程。
在Windows上,动态链接库就是一个dll文件;在Linux上,动态链接库是so文件。
如果在Linux上,那么调用的动态链接库文件名必须以lib开头。(Windows上无此限制。)
Java程序例子如下(来自张龙老师“深入浅出JNI第一讲”视频教程):
Java程序实例:
package com.meng.hellojni; public class HelloJNI { static // static代码块的执行时机,是在类被加载到JVM的时候 { // 告诉程序去哪里找本地方法的实现 System.loadLibrary("libHello");// 不要加后缀名,因为加载方式是系统相关的 } // 使用native关键字,说明本方法为本地方法,其实现由C/C++提供 public native void output(); public static void main(String[] args) { HelloJNI test = new HelloJNI(); test.output();// 使用native方法时,认定其实现已经提供,当做一个普通的Java方法,直接使用就可以 } }
本地代码
现在要写本地的实现。
C++代码一般由头文件和源程序文件两部分组成。
可以利用JDK中的javah工具,由Java代码生成需要的头文件。
先javac编译源文件,生成class文件,然后javah生成头文件如下:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_meng_hellojni_HelloJNI */ #ifndef _Included_com_meng_hellojni_HelloJNI #define _Included_com_meng_hellojni_HelloJNI #ifdef __cplusplus extern "C" { #endif /* * Class: com_meng_hellojni_HelloJNI * Method: output * Signature: ()V */ JNIEXPORT void JNICALL Java_com_meng_hellojni_HelloJNI_output (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
也就是说,这个工具会根据Java代码中的native声明,生成对应需要的头文件声明。
其中函数声明固定以Java开头,后面跟的是包名+类名+方法名,均以下划线分隔。
另外会加入两个参数,第一个为JNIEnv *,第二个为jobject。
在实现文件中,将头文件的函数声明拷过去,然后加上实现代码即可。
可以利用Visual Studio生成dll文件(需要include刚才生成的头文件和jni头文件(jni.h和jni_md.h)),然后把生成的dll文件放在Java程序找得到的路径下,注意程序中库和dll文件名字的对应,运行Java程序就可以调用。(本文这部分代码没有给出,有兴趣请自己实现)。
JNI数据映射
截图自电子书《Android NDK Beginner's Guide》 Chapter 3
资料收集
Oracle's JNI page for Java 6, including the JNI Specification
Best practices for using the Java Native Interface
JNI Complete tutorial with examples
Android Training: JNI Tips:
http://developer.android.com/training/articles/perf-jni.html