【JVM】本地方法接口 Native Interface
一、JNI简介
JVM本地方法接口(Java Native Interface,JNI)是一种允许Java代码调用本地方法(如C或C++编写的方法)的机制。这种技术通常用于实现高性能的计算密集型任务,或者与底层系统库进行交互。
二、JNI组成
-
Java类中的native方法:在Java类中使用native关键字声明一个本地方法,表示该方法将由本地代码实现。
-
JNI头文件:使用Java Native Interface工具(javac、javah)生成本地方法的头文件,该头文件中包含了本地方法的声明和参数列表等信息。
-
本地代码实现:根据生成的头文件,在本地代码中实现对应的本地方法。可以使用C、C++等语言编写本地代码,并通过编译器将其编译成动态链接库(DLL)或共享库(SO)。
三、JNI的作用
-
提高性能:通过将计算密集型任务交给本地代码实现,可以提高程序的性能。因为本地代码可以直接操作内存和硬件资源,而不需要经过Java虚拟机的额外开销。
-
与底层系统库交互:JNI可以方便地与底层系统库进行交互,例如访问操作系统、数据库、网络等资源。
-
扩展Java功能:通过JNI,可以将其他编程语言的功能集成到Java程序中,从而扩展Java的功能。
四、本地方法
简单来讲,一个Native Method就是一个Java调用非Java代码的接口。一个Native Method是这样一个java方法:该方法的实现由非Java语言实现,比如C。这个特征并非Java特有,很多其他的编程语言都有这一机制,比如在C++ 中,你可以用extern “C” 告知C++ 编译器去调用一个C的函数。
在定义一个native method时,并不提供实现体(有些像定义一个Java interface),因为其实现体是由非java语言在外面实现的。
本地接口的作用是融合不同的编程语言为Java所用,它的初衷是融合C/C++程序。
标识符native可以与所有其它的java标识符连用,但是abstract除外。这是合理的,因为native暗示这些方法是有实现体的,只不过这些实现体是非java的,但是abstract却显然的指明这些方法无实现体。native与其它java标识符连用时,其意义同非Native Method并无差别,比如native static表明这个方法可以在不产生类的实例时直接调用,这非常方便,比如当你想用一个native method去调用一个C的类库时。上面的第三个方法用到了native synchronized,JVM在进入这个方法的实现体之前会执行同步锁机制(就像java的多线程。)
一个native method方法可以返回任何java类型,包括非基本类型,而且同样可以进行异常控制。这些方法的实现体可以制一个异常并且将其抛出,这一点与java的方法非常相似。当一个native method接收到一些非基本类型时如Object或一个整型数组时,这个方法可以访问这非些基本型的内部,但是这将使这个native方法依赖于你所访问的java类的实现。有一点要牢牢记住:我们可以在一个native method的本地实现中访问所有的java特性,但是这要依赖于你所访问的java特性的实现,而且这样做远远不如在java语言中使用那些特性方便和容易。
native method的存在并不会对其他类调用这些本地方法产生任何影响,实际上调用这些方法的其他类甚至不知道它所调用的是一个本地方法。JVM将控制调用本地方法的所有细节。需要注意当我们将一个本地方法声明为final的情况。用java实现的方法体在被编译时可能会因为内联而产生效率上的提升。但是一个native final方法是否也能获得这样的好处却是值得怀疑的,但是这只是一个代码优化方面的问题,对功能实现没有影响。
如果一个含有本地方法的类被继承,子类会继承这个本地方法并且可以用java语言重写这个方法(这个似乎看起来有些奇怪),同样的如果一个本地方法被fianl标识,它被继承后不能被重写。
本地方法非常有用,因为它有效地扩充了jvm.事实上,我们所写的java代码已经用到了本地方法,在sun的java的并发(多线程)的机制实现中,许多与操作系统的接触点都用到了本地方法,这使得java程序能够超越java运行时的界限。有了本地方法,java程序可以做任何应用层次的任务。
五、使用native method
1. 与Java环境外交换
需要和Java外面的环境进行交互,这是本地方法存在的主要原因。比如和操作系统或者某些硬件交换信息时,本地方法就为我们提供了方便简洁的接口。
2. 与操作系统交互
通过使用本地方法,Java实现了JRE与底层系统的交互,甚至JVM的一部分就是使用 C 写的。另外如果我们要使用Java未提供的封装的操作系统的特性时,也需要使用到本地方法。就像Java创建的线程最终还是要回归到操作系统的本地线程。
3. Sun’s Java
Sun的解释器是用 C 实现的,使得它能像一些普通的 C 一样与外部交互。例如类 java.lang.Thread 的 setPriority() 方法是通过java 实现的,但是它实际调用的是该类里的本地方法 setPriority0()。
六、JNI源码解读
JNI源码解读主要包括以下几个部分:
-
JNI头文件:包含JNI函数声明和结构体定义。例如,jintArray、jbooleanArray等类型的声明。
-
JNI函数实现:这些函数是在C或C++中实现的,它们提供了与JNI头文件中声明的函数对应的本地方法。例如,GetStringUTFChars、ReleaseStringUTFChars等函数。
-
JNI函数指针:这些指针指向JNI函数实现。在Java代码中,可以使用这些指针来调用本地方法。
-
Java类和方法:这些类和方法用于在Java代码中声明本地方法。例如,public native void nativeMethod();表示一个本地方法。
-
加载和链接本地库:在Java程序启动时,需要加载包含本地方法实现的本地库。然后,JVM会将这些本地方法与Java类和方法关联起来。
以下是一个简单的JNI源码示例:
#include <jni.h>
#include "HelloJNI.h"
#include <stdio.h>JNIEXPORT jstring JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject obj) {return (*env)->NewStringUTF(env, "Hello from C!");
}
在这个示例中,我们实现了一个名为sayHello的本地方法,它返回一个字符串"Hello from C!"。要使用这个本地方法,需要在Java代码中声明它:
public class HelloJNI {static {System.loadLibrary("hello-jni");}public native String sayHello();public static void main(String[] args) {HelloJNI hello = new HelloJNI();String result = hello.sayHello();System.out.println(result);}
}
编译并运行这个Java程序,将看到输出"Hello from C!"。
七、结语
目前该方法的使用越来越少了,除非是与硬件有关的应用,比如通过java程序驱动打印机或者java系统管理生产设备,在企业级应用已经比较少见。因为现在的异构领域间的通信很发达,比如可以使用Socket通信,也可以是用Web Service等等。
需要注意的是,由于本地方法可能会破坏Java的安全性和可移植性,因此在使用JNI时需要谨慎操作。此外,虚拟机保证在同一Java线程中多次调用同一本地方法时,传递给该本地方法的JNI接口指针是相同的。
相关文章:

【JVM】本地方法接口 Native Interface
一、JNI简介 JVM本地方法接口(Java Native Interface,JNI)是一种允许Java代码调用本地方法(如C或C编写的方法)的机制。这种技术通常用于实现高性能的计算密集型任务,或者与底层系统库进行交互。 二、JNI组…...

JS 本地存储 sessionStorage localStorage
本地存储 随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在本地存储大量的数据,HTML5规范提出了相关解决方案。 本地存储特性 1、数据存储在用户浏览器中 2…...

K8S 存储卷
意义:存储卷----数据卷 容器内的目录和宿主机的目录进行挂载 容器在系统上的生命周期是短暂的,delete,k8s用控制器创建的pod,delete相当于重启,容器的状态也会回复到初始状态 一旦回到初始状态,所有的后天编辑的文件…...
一个SqlSugar实际案例
SqlGugar是一个非常好的数据库操作框架,今天用一个示例来分享如何使用。 新建一张课程表 结构如下: CREATE TABLE t_course (id int NOT NULL AUTO_INCREMENT COMMENT ID,title varchar(1024) NOT NULL COMMENT 课程标题,description text NOT NULL C…...

【RT-DETR有效改进】ShapeIoU、InnerShapeIoU关注边界框本身的IoU(包含二次创新)
前言 大家好,我是Snu77,这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进,内容持续更新,每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本,同时修改内容也支持Re…...

从理论到实践:数字孪生技术的全面应用探讨
数字孪生是一种将实际物体或系统的数字模型与其实时运行状态相结合的概念。这一概念的核心在于创建一个虚拟的、与真实世界相对应的数字副本,以便监测、分析和优化实体系统的性能。 简单理解,数字孪生就是在一个设备或系统的基础上,创造一个…...

2.1.2 一个关于y=ax+b的故事
跳转到根目录:知行合一:投资篇 已完成: 1、投资&技术 1.1.1 投资-编程基础-numpy 1.1.2 投资-编程基础-pandas 1.2 金融数据处理 1.3 金融数据可视化 2、投资方法论 2.1.1 预期年化收益率 2.1.2 一个关于yaxb的…...

Rust-解引用
“解引用”(Deref)是“取引用”(Ref)的反操作。取引用,我们有&、&mut等操作符,对应的,解引用,我们有操作符,跟C语言是一样的。示例如下: 比如说,我们有引用类型p:&i32;,那么可以用符…...
记录一下vue项目引入百度地图
公共部分 #allmap { width: 500px; height: 500px; font-family: "微软雅黑"; } 1、 <div id"allmap"> <baidu-map :center"center" :zoom"zoom" ready"handler"></baidu-map> </div> data()…...
基于Docker官方php:7.4.33-fpm镜像构建支持67个常见模组的php7.4.33镜像
实践说明:基于RHEL7(CentOS7.9)部署docker环境(23.0.1、24.0.2),所构建的php7.4.33镜像应用于RHEL7-9(如AlmaLinux9.1),但因为docker的特性,适用场景是不限于此的。 文档形成时期:2017-2023年 因系统或软件版本不同&am…...
opencv通过轮廓点生成闭合图像
前言 有时候需要将某一些点生成闭合的二值图像。记录一下。 // 轮廓点个数 int nrCurvePoints curContour.nr; // 轮廓点 DIM2DL* curvePoints curContour.pts;std::vector<cv::Point> points; // 轮廓点集合 for (int cntPoint 0; cntPoint < nrCurvePoints; cn…...

Python 网络编程之TCP详细讲解
【一】传输层 【1】概念 传输层是OSI五层模型中的第四层,负责在网络中的两个端系统之间提供数据传输服务主要协议包括**TCP(传输控制协议)和UDP(用户数据报协议)** 【2】功能 **端到端通信:**传输层负责…...
直饮水系统服务认证:提升水质与安全的必要举
直饮水系统作为一种便捷、卫生的饮水方式,已经越来越受到人们的欢迎。然而,随着市场的发展,直饮水系统的质量和服务也面临着一些挑战。因此,直饮水系统服务认证应运而生,成为了提升水质与安全的必要举措。 一、直饮水…...

Qt 调试系统输出报警声以及添加资源
文章目录 前言一、方法1 使用 Qsound1.添加都文件 直接报错2.解决这个错误 添加 QT multimedia3. 加入代码又遇到新的错误小结 二、第二种方法1.引入库2.添加资源2.1依次点击Qt--->Qt Resource File--->Choose2.2给资源文件起个名字,如:res&#…...

Linux下文件的创建写入读取编程
在linux下操作一个文件,首先要保证文件的存在(不存在就创建),接着打开文件(打开成功)并得到文件描述符,接着在进行读写操作,最后还需要关闭文件。如果我们对文件进行读写之后不关闭文…...
python 解析
list(pd.DataFrame) # 所有列名切片:print("显式 切片:\n", df.loc[:, "number":"sum"]) 所有行,列是从number 到sum ,前闭后开print("隐式 切片:\n", df.iloc[:, 1:3]) # 结果和上面一样转化成字典…...

谷歌aab包在Android 14闪退而apk没问题(targetsdk 34)
问题原因 Unity应用(target SDK 34)上线到GooglePlay,有用户反馈fold5设备上(Android14系统)疯狂闪退,经测试,在小米手机Android14系统的版本复现成功了,奇怪的是apk直接安装没问题,而打包成aa…...
34.在排序数组中查找元素的第一个和最后一个位置
34.在排序数组中查找元素的第一个和最后一个位置 给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。 如果数组中不存在目标值 target,返回 [-1, -1]。 你必须设计并实现时间复杂度为…...
js树过滤
// 递归过滤得到每一项的hidden为false的数据 function filterTree(arr) { return arr.filter(item > { if (item.children) { item.children filterTree(item.children) } if (!item.hidden) { return true } }) }...

Java多线程并发篇----第十六篇
系列文章目录 文章目录 系列文章目录前言一、线程等待(wait)二、线程睡眠(sleep)三、线程让步(yield)四、线程中断(interrupt)五、Join 等待其他线程终止前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官
。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...
git: early EOF
macOS报错: Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...
[特殊字符] 手撸 Redis 互斥锁那些坑
📖 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作,想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁,也顺便跟 Redisson 的 RLock 机制对比了下,记录一波,别踩我踩过…...

Linux-进程间的通信
1、IPC: Inter Process Communication(进程间通信): 由于每个进程在操作系统中有独立的地址空间,它们不能像线程那样直接访问彼此的内存,所以必须通过某种方式进行通信。 常见的 IPC 方式包括&#…...
虚幻基础:角色旋转
能帮到你的话,就给个赞吧 😘 文章目录 移动组件使用控制器所需旋转:组件 使用 控制器旋转将旋转朝向运动:组件 使用 移动方向旋转 控制器旋转和移动旋转 缺点移动旋转:必须移动才能旋转,不移动不旋转控制器…...