JNI样例

什么是JNI

The Java Native Interface (JNI) is a foreign function interface programming framework that enables Java code running in a Java virtual machine (JVM) to call and be called by native applications (programs specific to a hardware and operating system platform) and libraries written in other languages such as C, C++ and assembly.

Wiki百科的解释。

简单来说就是Java调用原生应用(硬件操作系统级别)的接口。有一种说法是能不用就别用,原因很多,移植性,安全性,内存,线程等都会有很多挑战。

但是出于某些原因,我们没得选。来来来,我们挑战一下。

JNI的样例
  1. 新建一个Java

    package com.uncledonghuang.jni;
    
    public class JniHello {
    
        /**
         * JNI say hello
         */
        public static native void nativeSayHello();
    }
    
  2. 生成C++头文件(如果您不知道什么头文件,可以尝试Google一下;一般来说C++头文件.h声明函数,源文件.cpp放置具体实现。表述不一定准确,C++真的很难)

    javac -h . com/uncledonghuang/jni/JniHello.java
    

    注意执行javac的工作目录,我们会看到生成的结果文件com_uncledonghuang_jni_JniHello.h如下

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class com_uncledonghuang_jni_JniHello */
    
    #ifndef _Included_com_uncledonghuang_jni_JniHello
    #define _Included_com_uncledonghuang_jni_JniHello
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     com_uncledonghuang_jni_JniHello
     * Method:    nativeSayHello
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_com_uncledonghuang_jni_JniHello_nativeSayHello
      (JNIEnv *, jclass);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    

    正如文件里的注释写的,为了避免麻烦,不要编辑这个文件

  3. 添加实现文件com_uncledonghuang_jni_JniHello.cpp

    #include "com_uncledonghuang_jni_JniHello.h"
    #include <iostream>
    
    JNIEXPORT void JNICALL Java_com_uncledonghuang_jni_JniHello_nativeSayHello(JNIEnv *, jclass) {
        std::cout << "Hello from native C++ !!" << std::endl;
    }
    
  4. 编译C++源文件

    • macOS平台
    g++ -c -fPIC -I${JAVA_HOME}/include \
    -I${JAVA_HOME}/include/darwin \
    com_uncledonghuang_jni_JniHello.cpp \
    -o com_uncledonghuang_jni_JniHello.o
    
    • Linux平台
    g++ -c -fPIC -I${JAVA_HOME}/include \
    -I${JAVA_HOME}/include/linux \
    com_uncledonghuang_jni_JniHello.cpp \
    -o com_uncledonghuang_jni_JniHello.o
    
    • Window平台(没测试过)
    g++ -c -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 com_uncledonghuang_jni_JniHello.cpp -o com_uncledonghuang_jni_JniHello.o
    
  5. 链接C++共享库

    • macOS平台
    g++ -dynamiclib -lc -o libJniHello.dylib com_uncledonghuang_jni_JniHello.o
    
    • Linux平台
    g++ -shared -fPIC -lc -o libJniHello.so com_uncledonghuang_jni_JniHello.o
    
    
    • Window平台(没测试过)
    g++ -shared -Wl,--add-stdcall-alias -o JniHello.dll com_uncledonghuang_jni_JniHello.o
    
  6. 加载动态链接库

    有2种方式可以加载动态链接库,一种是加载库名

    System.loadLibrary("JniHello");
    

    这种方式可以加载动态链接库如libJniHello.dylib libJniHello.soJniHello.dll

    还有一种方式是加载动态链接库文件,如

    System.load("/usr/local/lib64/libJniHello.dylib");
    

    可以根据需要使用不同的方式加载动态链接库。

    修改JniHello.java加载动态链接库,增加main方法,代码如下

    package com.uncledonghuang.jni;
    
    public class JniHello {
    
        static {
            System.loadLibrary("JniHello");
        }
    
        public static void main(final String[] args) {
            JniHello.nativeSayHello();
        }
    
        /**
         * JNI say hello
         */
        public static native void nativeSayHello();
    }
    
    
  7. 编译运行Java JNI

编辑Java

javac com/uncledonghuang/jni/JniHello.java

运行Java

java -cp . -Djava.library.path=. com.uncledonghuang.jni.JniHello

可以看到输出结果

Hello from native C++ !!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值