搭建简单JNI的experience

  一、背景

  有时,应用需要访问的系统特性和设备通过java平台是无法实现的,这时我们使用jni技术。

二、步骤

2.1 在本地声明一个本地方法

public class HelloNative {
    
    //native本地方法关键字
    public static native void greeting();
    
}

项目结构如图:

2.2 运行javah(jdk 8),javac -h(jdk 10+)获得包含该方法的C声明的头文件

 注意,从jdk10开始,javah命令就被删除了,使用javac -h A.java直接生成A.class和A.h文件。cd到.java文件的目录,执行以下命令:

其中./代表生成的class和h文件的存储目录,一定要写,不然会报错

此命令在当前目录生成了.class和.h文件

2.3 用C实现该本地方法

新建一个C项目,将HelloNative.h拷贝进去

生成的.h文件内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloNative */

#ifndef _Included_HelloNative
#define _Included_HelloNative
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloNative
 * Method:    greeting
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloNative_greeting
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

发现include<jni.h>位置报错:“jni.h" not found。

跑到jdk/include目录下找到jni.h,放到helloNative.h同目录下

将include<jni.h>改成include "jni.h"解决该报错


该报错解决吼,发现JNIEXPORT飘红,JNIEXPORT变量找不到,跑到jdk/include/win32下找到jni_md.h,放到helloNative.h同目录下,报错解决

新建HelloNative.c,放到helloNative.h同目录下,实现该头文件的函数Java_HelloNative_greeting;

//
// Created by wangwenxuan on 2019/12/7.
//

#include "HelloNative.h"

JNIEXPORT void JNICALL Java_HelloNative_greeting
(JNIEnv *env, jclass object){
    printf("Hello World");
}

此时C项目结构如下:

2.4 将代码置于共享库中

unix和类unix平台打包成.so文件,windows平台打包成.dll文件。

windows平台方法

(1)使用cmakeList  和cmake. make 打包(要下载cmake)

   (2)  使用gcc命令,MingW等带有该命令的执行文件,为该执行文件设置环境变量即可

  (3)一些编译器自带生成.dll文件的方法,比如Vs

使用gcc方法如下:

Windows下下载MinGW

接下来就是使用GCC对HelloJNI.c编译,在Terminal窗口输入如下:

C:\Users\wangwenxuan\CLionProjects\HelloNative>gcc -c HelloNative.c

完成编译。此时在项目中会生成HelloJNI.o文件。接下来是将HelloJNI.o转为HelloJNI.dll,即转为windows平台下的动态链接库。在Terminal中输入如下:

C:\Users\wangwenxuan\CLionProjects\HelloNative>gcc -Wl,--add-stdcall-alias -shared -o hello.dll HelloNative.o

会在HelloNative.c同目录生成.dll文件,目录结构如下:

2.5 在Java程序中加载此类库

public class HelloNativeTest {
    static{
        System.loadLibrary("hello");
    }
    public static void main(String[] args){
        HelloNative.greeting();
    }
}

 java程序结构:

运行结果:

可能出现的错误

  • java.library.path找不到dll的错误,
Exception in thread "main" java.lang.UnsatisfiedLinkError: no hello in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
    at java.lang.Runtime.loadLibrary0(Runtime.java:870)
    at java.lang.System.loadLibrary(System.java:1122)
    at com.huachao.java.HelloJNI.<clinit>(HelloJNI.java:8)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:123)

Process finished with exit code 1

即找不到我们生成的dll文件。可以在library的path中加入我们的dll文件

File——Project Structure——Libraries——新建Java library,选中我们生成的dll文件即可。

  • 32bit和64bit的冲突。是gcc版本和jdk版本的冲突,有一个是32位一个64位,重新下载改成一致的

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值