2.1 Overview
write a simple Java application that calls a C function to print “Hello World!”. The pro-
cess consists of the following steps:1. Create a class (HelloWorld.java) that declares the native method.
2. Use javac to compile the HelloWorld source file, resulting in the class file
HelloWorld.class. The javac compiler is supplied with JDK or Java 2 SDK releases.
3. Use javah -jni to generate a C header file (HelloWorld.h) containing the
function prototype for the native method implementation. The javah tool is
provided with JDK or Java 2 SDK releases.
4. Write the C implementation (HelloWorld.c) of the native method.
5. Compile the C implementation into a native library, creating HelloWorld.dll
or libHelloWorld.so. Use the C compiler and linker available on the host environment.
6. Run the HelloWorld program using the java runtime interpreter. Both the
class file (HelloWorld.class) and the native library (HelloWorld.dll or libHelloWorld.so) are loaded at runtime.
The remainder of this chapter explains these steps in detail.
觉得挺好,翻译一下啊:
写一个java应用,调用c函数打印“Hello World”,整个过程又一下几步组成:
1、创建一个类(HelloWorld.java),并在该类中声明native方法,即本地方法。
2、使用javac编译这个源文件,生成字节码文件HelloWorld.class,这个编译器在jdk或java2SDK以上都支持
3、使用javah -jni 生成一个C头文件,HelloWorld.h,这个文件中包含了这些c函数原型本地方法实现,其实就是声明c函数
4、写一个本地方法的用C语言实现的HelloWorld.c
5、使用主机上可用的C编译器和连接器,编译C的成为一个本地库,创建为HelloWorld.dll(windows),或者libHelloWorld.so(linux)
6、用java运行时解析器运行HelloWorld程序,HelloWorld.class和本地库HelloWorld.dll获libHelloWorld.so都被加载到运行时虚拟机了
我看的是这本书,《The JavaTM Native Interface》 Programmer’s Guide and Specification,听不错的
HelloWorld小例子
1、写HelloWorld.java
class HelloWorld {
private native void print();
public static void main(String[] args) {
new HelloWorld().print();
}
static {
System.loadLibrary("HelloWorld");
}
}
2、编译生成字节码文件
命令:javac HelloWorld.java ->生成了HelloWorld.class
编译生成本地调用头文件HelloWorld.h
命令:javah -jni HelloWorld
/* 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: print
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_print
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
3、编写HelloWorld.c
#include <jni.h>
#include <stdio.h>
#include "HelloWorld.h"
JNIEXPORT void JNICALL
Java_HelloWorld_print(JNIEnv *env, jobject obj)
{
printf("Hello World!\n");
return;
}
4、编译生成动态连接库-> libHelloWorld.so
命令: gcc -shared -I /usr/lib/jvm/jdk1.7/include/ -I /usr/lib/jvm/jdk1.7/include/linux/ HelloWorld.c -o libHelloWorld.so
-shared 指明是生成动态连接库
-I (小写字母i的大写)是生成此目标文件需要导入的库(缩写为import)
其中jni.h在/usr/lib/jvm/jdk1.7/include/ 下
jni.h中又包含了jni_md.h,文件在/usr/lib/jvm/jdk1.7/include/linux/下
HelloWorld.c指明要编译的c文件
-o 指明要生成的目标文件
注意:不要在HelloWorld.c前加-c这样编译出来的文件就是可执行文件了,而不是动态连接库
5、在java虚拟机上运行
命令:java HelloWorld,会报错,如下:
~/test/jni$ java HelloWorld
Exception in thread "main" java.lang.UnsatisfiedLinkError: no HelloWorld in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1860)
at java.lang.Runtime.loadLibrary0(Runtime.java:845)
at java.lang.System.loadLibrary(System.java:1084)
at HelloWorld.<clinit>(HelloWorld.java:8)
这是因为没有指定动态连接库的路径,java本地调用库的路径可以这样,
命令:export LD_LIBRARY_PATH=.
这表示把当前路径加入库中
再此运行:
命令:java HelloWorld
~/test/jni$ java HelloWorld
Hello World!