native关键字和JNI的概念
查看java Object类的源码,发现hashCode方法是这样实现的
public native int hashCode();
使用native关键字修饰了hashCode方法,那么native关键字到底有什么作用呢?
The native keyword is applied to a method to indicate that the method is implemented in native code using JNI (Java Native Interface).
StackOverflow 上给出了这样的回答(https://stackoverflow.com/questions/6101311/what-is-the-native-keyword-in-java-for)。
翻译一下,就是说 使用了native关键字的方法就说明这个方法是一个调用Java本地接口(Java Native Interface,即JNI)实现的方法。
那么问题来了,什么是JNI(Java本地接口呢)?
简单点说,就是用其他编程语言,主要是C或C++或汇编语言实现的接口。
通过JNI,Java可以调用一些由其他语言开发的功能,或者可以被其他的语言所调用,从而实现了Java和其他语言的双向连接。
一个简单的JNI接口示例
那么怎么实现一个简单的JNI接口呢?以用C语言实现JNI接口为例,具体步骤如下:
1 创建一个包含native接口的java类
public class HelloJNI {static {System.loadLibrary("hello"); // Load native library at runtime// hello.dll (Windows) or libhello.so (Unixes)}// Declare a native method sayHello() that receives nothing and returns voidprivate native void sayHello();// Test Driverpublic static void main(String[] args) {new HelloJNI().sayHello(); // invoke the native method}}
2 编译Java类并生成.h 文件
JDK 8 的编译命令
javac -h . HelloJNI.java
JDK 8之前的编译命令,分为两步
javac HelloJNI.javajavah HelloJNI
生成的 HelloJNI.h 如下所示
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class HelloJNI */#ifndef _Included_HelloJNI#define _Included_HelloJNI#ifdef __cplusplusextern "C" {#endif/** Class: HelloJNI* Method: sayHello* Signature: ()V*/JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif
3 创建C文件 HelloJNI.c
#include <jni.h>#include <stdio.h>#include "HelloJNI.h"// Implementation of native method sayHello() of HelloJNI classJNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject thisObj) {printf("Hello World!\n");return;}
4 生成本地类库文件,以Ubuntu 64位的操作系统为例
先导入JAVA_HOME的环境变量
export JAVA_HOME=/your/java/installed/direcho $JAVA_HOME
编译生成类库文件
gcc -fPIC -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" -shared -o libhello.so HelloJNI.c
5 运行java程序
java -Djava.library.path=. HelloJNI
上面的例子来自这篇文章(https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html#zz-2.1),里面还有C++的程序示例以及不同操作系统编译的命令,十分的详细。感兴趣的同学可以参考一下。
上面的例子亲测有效,需要注意的是编写第1步的java程序时,不要加上包名,如果加上包名还按后面的步骤执行的话,最后会报一个Error: Could not find or load main class HelloJNI 的错误。不加包名是可以的。




