美文网首页Java 杂谈
native 关键字和JNI 接口介绍

native 关键字和JNI 接口介绍

作者: joyhj | 来源:发表于2018-08-17 20:06 被阅读2次

    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 上给出了这样的回答

    翻译一下,就是说 使用了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 void
       private native void sayHello();
     
       // Test Driver
       public static void main(String[] args) {
          new HelloJNI().sayHello();  // invoke the native method
       }
    }
    

    2 编译Java类并生成.h 文件
    jdk 8 的编译命令

    javac -h . HelloJNI.java
    

    jdk8之前的编译命令,分为两步

    javac HelloJNI.java
    javah 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 __cplusplus
    extern "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 class
    JNIEXPORT 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/dir
    echo $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
    

    上面的例子来自这篇文章,里面还有C++的程序示例以及不同操作系统编译的命令,十分的详细。感兴趣的同学可以参考一下。

    上面的例子亲测有效,需要注意的是编写第1步的java程序时,不要加上包名,如果加上包名还按后面的步骤执行的话,最后会报一个Error: Could not find or load main class HelloJNI 的错误。不加包名是可以的。

    相关文章

      网友评论

        本文标题:native 关键字和JNI 接口介绍

        本文链接:https://www.haomeiwen.com/subject/qchobftx.html