native方法的声明只需要在签名式前添加native关键字。
在java中实现一个native方法的主要流程如下:
1.声明native方法;
2.使用javac编译java源码文件,生成字节码文件(.class);
3.使用javah生成native方法的头文件(.h);
4.创建相应的.c文件,实现.h文件中声明的native函数;
5.使用gcc编译.c文件,生成.so文件(linux系统中的动态库)
6.在java源文件中添加静态的加载上述so文件的代码。(熟悉这个流程后,这个步骤可以在第一步编辑java源文件时完成。
依上述步骤,实现一个HelloWorld的例子。
第一步、编辑HelloWorld.java文件:
public class HelloWorld{
public native void print();
public static void main(String argv[]){
HelloWorld hw = new HelloWorld();
System.out.println("In Java, before native");
hw.print();
System.out.println("In Java, after native");
}
static {
System.loadLibrary("HelloWorld");
}
}
第二步、编译
java
源文件:
$javac HelloWorld.java
$ls <= 当前应该只有HelloWorld.java和HelloWorld.class两个文件
第三步、使用
javah
生成
native
方法的
C
语言函数声明(
.h
文件)
$javah -jni HelloWorld
$ls <= 此时应该增加了一个HelloWorld.h文件
$cat -n 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: print
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_print
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
第四步、编辑
HelloWorld.c
文件,实现上述头文件中声明的函数
#include "stdio.h"
#include "HelloWorld.h"
JNIEXPORT void JNICALL Java_HelloWorld_print
(JNIEnv *jenv, jobject jobj)
{
int i = 0;
printf("In native: Hello World!\n");
for(i = 0; i < 5; i++)
printf("In native: loop %d\n", i);
// fflush(stdout);
}
第五步、编译
HelloWorld.c,
生成
libHelloWorld.so
文件
$gcc HelloWorld.c -g -I%JAVA_HOME%/include -I%JAVA_HOME%/include/linux-fPIC -shared -o libHelloWorld.so <=需用自己的java安装路径替换上面的%JAVA_HOME%,该步骤之后,会生成libHelloWorld.so文件
至此所有编译工作完成,使用
java
命令运行
.class
文件,
JVM
会自动加载
libHelloWorld.so
$java HelloWorld
InJava, before native
Innative: Hello World!
Innative: loop 0
Innative: loop 1
Innative: loop 2
Innative: loop 3
Innative: loop 4
InJava, after native
这样,native的代码的生成,编辑,编译,运行流程至此结束。
另外还有一个有用的java族命令,javap可以用来反编译class文件。当在native层的代码中需要调用java方法时,需要知道java方法的签名式。javap也可以用来生成java方法的签名式
$javap -s HelloWorld
Compiledfrom "HelloWorld.java"
publicclass HelloWorld {
publicHelloWorld();
Signature:()V
publicnative void print();
Signature:()V
publicstatic void main(java.lang.String[]);
Signature:([Ljava/lang/String;)V
static{};
Signature:()V
}