第一个Java调用C程序的HelloWord由下面几步构成:1. 创建HelloWord.java 并声明Native方法 2. 使用javac编译HelloWord源文件生成HelloWord.class 3.使用javah -jni生成C头文件HelloWord.h, 这个头文件包含本地方法的原型声明 4.编写本地方法的HelloWord.c实现,应当包含HelloWord.h 5.编译HelloWord.c生成HelloWord.dll( windows) 或libHelloWord.so(linux), 编译工具应当使用目标平台的编译器。6.运行程序,libHelloWord.so应当包含在环境变量,否则加载不到。下面详细介绍这几个步骤:
声明本地方法:
class HelloWorld {
private native void print();// 声明本地方法
public static void main(String[] args) {
new HelloWorld().print();//执行本地方法
}
static {
System.loadLibrary("HelloWorld");//加载实现了native方法的本地库,通过环境变量必须能找得到
}
}
native方法的声明和普通java方法的声明是不同的,1必须是native,2不能有具体实现
采用静态代码块加载库,能够保证在HelloWord.class程序的方法被执行之前, 我们编写的本地库能够被加载完毕, 这是static代码块的作用。调用本地方法和调用普通java方法没什么区别
编译我们的HelloWord.java 生成 HelloWord.class
javac HelloWorld.java
生成HelloWord.h ,必须生成HelloWord.class后我们才能运行这个命令
javah -jni HelloWorld
在HelloWord.h中有如下声明
JNIEXPORT void JNICALL Java_HelloWorld_print (JNIEnv *, jobject); // 忽略掉JNIEXPORT和JNICALL,就是一个标准的C方法声明
或许你注意到了 private native void print();并没有声明任何参数,但是生成的.h文件却包含两个参数(JNIEnv *, jobject), 第一个参数是每个实现native方法必须有的,我们使用JNI的一些列调用API都来自这个指针,第二个参数叫做this,也就是HelloWord这个对象了,当然我们的HelloWord太简单,并没有使用到这两个参数。
编写本地方法实现:
#include <jni.h>
#include <stdio.h>
#include "HelloWorld.h"
JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *env, jobject obj)
{
printf("Hello World!\n");
return;
}
例子很简单,只是调用了printf函数输出了一个字符串,这个字符串会打印在log里,通过logcat可以查到
jni.h使我们必须包含的一个头文件, JNIEXPORT JNICALL JNIEnv jobject 都在这个头文件中定义
stdio.h 不用说了,printf的声明。 HelloWord.h 是我们自己的, 注意:HelloWord.h HelloWord.c必须在同一个目录
编译成库:文档上介绍了一些命令,在这里我贴出来
cc -G -I/java/include -I/java/include/solaris
HelloWorld.c -o libHelloWorld.so
-G选项表明生成动态库,而不是可执行文件
cl -Ic:\java\include -Ic:\java\include\win32
-MD -LD HelloWorld.c -FeHelloWorld.dll
编译成库需要编译动态库,不同的平台有不同的方法, 不管用什么方法,关键字 :“动态库”
执行程序:
java HelloWord
你在logcat上应该可以看到如下输出:
Hello World!
在这里再次提醒你的环境变量,在加载库的时候,系统会自动到环境变量指明的路径里去寻找我们的动态库,如果找不到会报如下错误:
java.lang.UnsatisfiedLinkError: no HelloWorld in library path
at java.lang.Runtime.loadLibrary(Runtime.java)
at java.lang.System.loadLibrary(System.java)
at HelloWorld.main(HelloWorld.java)
怎么设置环境变量这里就不翻译了,每个平台有每个平台的方法,如果不会自己去查吧。
好了,今天的这个HelloWord 是不是一如既往的如同网上的教程一样简单呢,之后我们就详细讨论JNI