编译环境:
OS: OSX 10.7及以上
g++: i686-apple-darwin11-llvm-g++-4.2 (系统默认安装)
Java: 1.7.0_25 (jdk的下载链接: jdk-7u25-macosx-x64.dmg , 包含了JRE);
1. 在HelloWorld.java中创建HelloWorld类:
public class HelloWorld{
static {
System.loadLibrary("Hello");
}
public native void printHello();
public static void main(String[] args)
{
new HelloWorld().printHello();
}
}
line 2是static block, 在Java类的初始化阶段用于初始化静态变量; System.loadLibray("Hello")用于加载native c++ 代码编译生成的动态库,从后面的结果我们可以看到,在mac 下, 动态库的名字应该是libHello.jnilib; 之所以将System.loadLibrary("Hello")放到static block中,就是为了在类初始化时首先执行这部分代码,确保在类执行本地方法时已经加载了对应的库文件;
line 6,使用native关键字声明了一个方法void printHello(),表明这个方法将用native的方式实现;
2. 编译
$javac HelloWrold.java
3. 生成native头文件
$javah -jni HelloWorld
当前目录下可以看到已经生成了HelloWorld.h, 这是不可修改的代码,用于指定了native代码中需要实现的函数的原型; 执行cat HelloWorld.h后可以看到文件内容是:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloWorld
* Method: printHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_printHello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
4. 在HelloWorld.cpp文件中,添加native c++代码
#include <jni.h>
#include "HelloWorld.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_HelloWorld_printHello
(JNIEnv *, jobject)
{
printf("Hello, Java world!");
return ;
}
首先,需要包含头文件 jni.h,该文件定义了JNI的函数类型和数据结构;
接着需要包含上一步生成的native头文件HelloWorld.h;
最后,按照HelloWorld.h中声明的函数原型实现函数体;
$ g++ -dynamiclib -I /System/Library/Frameworks/JavaVM.framework/Headers Jni_HelloWorld_imp.cpp -o libHello.jnilib
-dynamiclib选项表示生成动态库,相当于linux环境下的-shared;
-I 指定编译的依赖的头文件所在的路径,在这里也就是jni.h所在的路径; linux环境下,路径可能是/usr/lib/jvm/java-xxx/include;
-o指定生成的动态库文件的名称,在Mac OS环境下,动态库的命名格式为libXXX.jnilib,相当于linux下的libXXX.so;
6. 运行
$ java HelloWorld
就可以看到运行期待已久的结果了:
Hello, Java world!