Java的JNI快速入门教程(推荐)

作者:jingxian 时间:2022-11-22 16:10:48 

1. JNI简介

JNI是Java Native Interface的英文缩写,意为Java本地接口。

问题来源:由于Java编写底层的应用较难实现,在一些实时性要求非常高的部分Java较难胜任(实时性要求高的地方目前还未涉及,实时性这类话题有待考究)。

解决办法:Java使用JNI可以调用现有的本地库(C/C++开发任何和系统相关的程序和类库),极大地灵活Java的开发。

2. JNI快速学习教程

2.1 问题:

使用JNI写一段代码,实现string_Java_Test_helloworld(JNIEnv *env, jclass cls , jstring j_str)函数,实现在字符串j_str("world")前面加上hello,并返回。

2.2 解决问题过程:

I. 编写Test.java类:


public class Test{
 // native interface
 public native String helloworld(String text);

public static void main(String[] args){
   // Load dynamic library
   System.loadLibrary("Test2");
   Test ts = new Test();
   String text = ts.helloworld("world");
   System.out.println(text);
 }
}

备注:

1、加载动态类库:System.loadLibrary("Test2");【Windows下加载的就是Test2.dll,Linux下加载的是Test2.so】

II. 编译Test.java文件

进入cmd输入命令 > javac Test.java

III. 生成Test.h文件

进入cmd输入命令 > javah Test

Test.h文件内容如下:


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

#ifndef _Included_Test
#define _Included_Test
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:   Test
* Method:  helloworld
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_Test_helloworld
(JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

备注:

1、函数声明,固定格式:JNIEXPORT;返回类型:jstring;JNI调用:JNICALL;Java_完整类名_方法名:Java_Test_helloworld;

2、函数参数:调用jni.h封装好的函数指针:JNIEnv;Java类本身:jobject,Java文件传入参数:jstring。

IV. 编写C语言文件Test2.c实现Test类调用动态链接库的功能:


#include "Test.h"
#include <string.h>

JNIEXPORT jstring JNICALL Java_Test_helloworld
(JNIEnv *env, jobject obj, jstring string){
 const char* str = (*env)->GetStringUTFChars(env,string,0);
 char cap[128];
 cap[0] = 'h';
 cap[1] = 'e';
 cap[2] = 'l';
 cap[3] = 'l';
 cap[4] = 'o';

strcat(cap,str);

(*env)->ReleaseStringUTFChars(env,string,0);
 return (*env)->NewStringUTF(env,cap);
}

备注:

1、由于Java本身使用了双字节字符,C语言本身都是单字节字符,所以需要使用(*env)->GetStringUTFChars()转换Java和C之间的字符串;

2、GetStringUTFChars()和NewStringUTF(),第一个是从UTF8转换为C的编码格式,第二个是根据C的字符串返回一个UTF8字符串;

3、ReleaseStringUTFChars()是用来释放对象的,在Java中有虚拟机进行垃圾回收,但是在C语言中这些对象必须手动回收,否则可能造成内存泄漏。

V. 编译和运行

编译:

进入cmd输入命令 > gcc -I "D:\Program Files\Java\jdk1.8.0_45\include" -I "D:\Program Files\Java\jdk1.8.0_45\include\win32" --share Test2.c -o Test2.dll

运行:

进入cmd输入命令 > java Test

运行结果如下:

helloworld

3. 总结:

第一步:编写带有native方法的Java类(Test.java),使用javac工具编译Java类(生成Test.class);

第二步:使用javah生成与native方法对应的头文件(Test.h);

第三步:使用C/C++实现相应的头文件(Test2.c),并编译为动态链接库(Test2.so)。

本文运行环境:Windows 64位操作系统,JDK 1.8版本,mingw64(GCC)。

标签:Java,JNI
0
投稿

猜你喜欢

  • springboot整合vue实现上传下载文件

    2023-11-14 07:10:37
  • spring-boot整合ehcache实现缓存机制的方法

    2023-06-18 20:05:10
  • Android自定义控件之日期选择控件使用详解

    2021-07-11 09:39:52
  • C#使用System.Net.Mail类实现邮件发送

    2022-04-26 01:38:21
  • java实现用户自动登录

    2023-11-10 14:38:59
  • JAVA演示阿里云图像识别API,印刷文字识别-营业执照识别

    2022-04-21 15:05:22
  • c# 反射+自定义特性保存数据至本地

    2023-03-14 03:07:40
  • MyBatis-Plus实现2种分页方法(QueryWrapper查询分页和SQL查询分页)

    2021-08-12 09:52:55
  • Java使用Hutool实现AES、DES加密解密的方法

    2021-06-03 16:49:57
  • mybatis plus新增(insert)数据获取主键id的问题

    2023-08-09 10:50:52
  • Java实现将PDF转为PDF/A

    2023-03-16 00:54:22
  • Java获得当前时间前指定几个小时具体时间的方法示例

    2023-11-24 04:56:49
  • C# 面向对象三大特性:封装、继承、多态

    2022-09-15 17:00:53
  • flutter实现底部导航栏

    2023-08-23 01:06:13
  • Java实现一个顺序表的完整代码

    2023-09-21 01:00:59
  • java查找字符串中的包含子字符串的个数实现代码

    2022-08-15 17:48:45
  • Android平台预置GMS包后关机闹钟失效问题及解决方法

    2022-12-31 05:52:33
  • C#使用Object类实现栈的方法详解

    2021-08-03 17:36:16
  • C#后台创建控件并获取值的方法

    2022-10-20 08:39:46
  • SpringBoot+Prometheus+Grafana实现应用监控和报警的详细步骤

    2023-10-02 06:40:26
  • asp之家 软件编程 m.aspxhome.com