JAVA本地接口(JNI)

简介:

JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++)。从Java1.1开始,JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他编程语言,只要调用约定受支持就可以了。使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的。例如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少要保证本地代码能工作在任何Java 虚拟机环境下。
JNI编写步骤:

  1. 编写带有native声明的方法的java类
  2. 使用javac命令编译所编写的java类
  3. 使用javah + java类名生成扩展名为h的头文件
  4. 使用C/C++实现本地方法
  5. 将C/C++编写的文件生成动态连接库

首先,我们来编写JAVA类

public class HelloJNI
{
   // 所有native关键词修饰的都是对本地的声明
   public native void displayHelloJNI();

   static
   {
      // 载入本地动态链接库库
      System.loadLibrary("HelloJNI");
   }

   public static void main(String[] args)
   {
      new HelloJNI().displayHelloJNI();
   }
}

编写完JAVA类后,我们需要对其进行编译获得字节码文件:javac HelloJNI.java

这里写图片描述

然后我们要生成扩展名为h的头文件:javah HelloJNI

生成的头文件内容如下:

/* 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:    displayHelloJNI
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloJNI_displayHelloJNI
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

下面我们需要引入刚才生成的头文件并实现其方法,最终生成动态链接库。

c源文件代码如下:

#include <stdio.h>
#include "HelloJNI.h"

JNIEXPORT void JNICALL Java_HelloJNI_displayHelloJNI(JNIEnv *env, jobject obj)
{
   printf("HelloJNI\n");
}

这里使用VC的编译器:cl -I%java_home%\include -I%java_home%\include\win32 -LD HelloJNIImpl.c -FeHelloJNI.dll

我们需要将生成的HelloJNI.dll放到JAVA的类路径下,最后运行JAVA程序。
控制台会输出:HelloJNI

到此,最简单的JNI编写过程已经完了。下面我们来总结一下。

JNI数据类型对应关系
基本类型

Java类型 本地C类型 说明
boolean jboolean 无符号8位整型(unsigned char)
byte jbyte 有符号8位整型(char)
char jchar 无符号16位整型(unsigned short)
short jshort 有符号16位整型(short)
int jint 有符号32位整型(int)
long jlong 有符号64位整型(long)
float jfloat 32位浮点型(float)
double jdouble 64位浮点型(double)

引用数据类型

Java类型 本地C类型 说明
Object jobject 任何JAVA对象,或者没有对应JAVA类型的对象
Class jclass Class类对象
String jstring 字符串对象
Object[] jobjectArray 任何对象的数组
boolean[] jbooleanArray 布尔型数组
byte[] jbyteArray 比特型数组
char[] jcharArray 字符型数组
short[] jshortArray 短整型数组
int[] jintArray 整型数组
long[] jlongArray 长整型数组
float[] jfloatArray 浮点型数组
double[] jdoubleArray 双浮点型数组

特殊类型

Java类型 本地C类型 说明
void void N/A

注意:
1. 引用数据类型则不能直接使用,需要根据JNI函数进行相应的转换后,才能使用。
2. 多维数组(包括二维数组)都是引用类型,需要使用 jobjectArray 类型存取其值 。

例如:二维整型数组就是指向一维数组的数组,其声明使用方式如下:

//获得一维数组 的类引用,即jintArray类型  
jclass intArrayClass = env->FindClass("[I");   
//构造一个指向jintArray类一维数组的对象数组,该对象数组初始大小为dimion  
jobjectArray obejctIntArray  =  env->NewObjectArray(dimion ,intArrayClass , NULL);  
目录
相关文章
|
4月前
|
消息中间件 缓存 前端开发
从资损百万到零事故:Java 接口幂等设计的艺术与实践
在分布式系统中,重复请求常引发严重资损,如支付双扣、库存超卖等问题,其根源在于接口缺乏幂等性设计。本文通过真实案例揭示幂等性的重要性,并详解8种主流解决方案,涵盖唯一请求ID、乐观锁、悲观锁、状态机等,帮助开发者构建稳定系统,保障业务一致性。无论你是架构师还是开发工程师,都能从中获得实战指导,有效规避重复调用带来的风险。
323 2
|
4月前
|
数据采集 JSON Java
Java爬虫获取1688店铺所有商品接口数据实战指南
本文介绍如何使用Java爬虫技术高效获取1688店铺商品信息,涵盖环境搭建、API调用、签名生成及数据抓取全流程,并附完整代码示例,助力市场分析与选品决策。
|
3月前
|
算法 安全 Java
除了类,Java中的接口和方法也可以使用泛型吗?
除了类,Java中的接口和方法也可以使用泛型吗?
154 11
|
2月前
|
Java Go 开发工具
【Java】(9)抽象类、接口、内部的运用与作用分析,枚举类型的使用
抽象类必须使用abstract修饰符来修饰,抽象方法也必须使用abstract修饰符来修饰,抽象方法不能有方法体。抽象类不能被实例化,无法使用new关键字来调用抽象类的构造器创建抽象类的实例。抽象类可以包含成员变量、方法(普通方法和抽象方法都可以)、构造器、初始化块、内部类(接 口、枚举)5种成分。抽象类的构造器不能用于创建实例,主要是用于被其子类调用。抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类abstract static不能同时修饰一个方法。
223 1
|
4月前
|
存储 缓存 安全
Java集合框架(二):Set接口与哈希表原理
本文深入解析Java中Set集合的工作原理及其实现机制,涵盖HashSet、LinkedHashSet和TreeSet三大实现类。从Set接口的特性出发,对比List理解去重机制,并详解哈希表原理、hashCode与equals方法的作用。进一步剖析HashSet的底层HashMap实现、LinkedHashSet的双向链表维护顺序特性,以及TreeSet基于红黑树的排序功能。文章还包含性能对比、自定义对象去重、集合运算实战和线程安全方案,帮助读者全面掌握Set的应用与选择策略。
281 23
|
4月前
|
安全 Java 开发者
Java集合框架:详解Deque接口的栈操作方法全集
理解和掌握这些方法对于实现像浏览器后退功能这样的栈操作来说至关重要,它们能够帮助开发者编写既高效又稳定的应用程序。此外,在多线程环境中想保证线程安全,可以考虑使用ConcurrentLinkedDeque,它是Deque的线程安全版本,尽管它并未直接实现栈操作的方法,但是Deque的接口方法可以相对应地使用。
263 12
|
4月前
|
存储 安全 Java
Java集合框架(一):List接口及其实现类剖析
本文深入解析Java中List集合的实现原理,涵盖ArrayList的动态数组机制、LinkedList的链表结构、Vector与Stack的线程安全性及其不推荐使用的原因,对比了不同实现的性能与适用场景,帮助开发者根据实际需求选择合适的List实现。
|
4月前
|
Java API 网络架构
java调用api接口自动判断节假日信息
java调用api接口自动判断节假日信息
1389 0
|
5月前
|
存储 安全 Java
深入理解Java序列化接口及其实现机制
记住,序列化不仅仅是把对象状态保存下来那么简单,它涉及到类的版本控制、安全性和性能等多个重要方面。正确理解和实现Java序列化机制对于构建高效、安全和可维护的Java应用至关重要。
212 0