【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的作用

  1. 提高性能:通过将计算密集型任务交给本地代码实现,可以提高程序的性能。因为本地代码可以直接操作内存和硬件资源,而不需要经过Java虚拟机的额外开销。

  2. 与底层系统库交互:JNI可以方便地与底层系统库进行交互,例如访问操作系统、数据库、网络等资源。

  3. 扩展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接口指针是相同的。

图片

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/612497.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python教程16:使用海龟画图turtle画会动的时钟

---------------turtle源码集合--------------- Python教程36&#xff1a;海龟画图turtle写春联 Python源码35&#xff1a;海龟画图turtle画中国结 Python源码31&#xff1a;海龟画图turtle画七道彩虹 Python源码30&#xff1a;海龟画图turtle画紫色的小熊 Python源码29&a…

CRMEB多商户短信开发

在使用CRMEB多商户系统的时候&#xff0c;想要二开使用其他平台的短信&#xff0c;这里以阿里云短信为例的具体实现方法。 一、加载阿里云短信的SDK&#xff0c;执行命令&#xff1a;composer require alibabacloud/dysmsapi-20170525 二、增加阿里云短信的驱动 1.在 crmeb\…

【REST2SQL】07 GO 操作 Mysql 数据库

【REST2SQL】01RDB关系型数据库REST初设计 【REST2SQL】02 GO连接Oracle数据库 【REST2SQL】03 GO读取JSON文件 【REST2SQL】04 REST2SQL第一版Oracle版实现 【REST2SQL】05 GO 操作 达梦 数据库 【REST2SQL】06 GO 跨包接口重构代码 MySQL是一个关系型数据库管理系统&#xf…

什么是编程思路?如何训练提升自己的编程思路?

哈喽&#xff0c;大家上午好呀&#xff01;又和大家如期见面了&#xff01; 今天给大家分享改变编程思路的9条技巧。 1.拆分项目&#xff0c;再编程 先按大类写子程序&#xff0c;例如自动&#xff0c;手动&#xff0c;报警&#xff0c;然后子程序中写FB块&#xff0c;FC程序&…

el-upload实现可替换、删除、预览的图片上传。js 往返缓存(可判断当前页面是不是返回的页面)

el-upload实现可替换、删除、预览的图片上传 组件使用&#xff1a; <template><div><UploadImage sendUrl :limit"1" :size"size" :gifSize"gifSize" v-model"images"></UploadImage> </div> </tem…

【Linux】Linux系统编程——Linux目录结构

Linux的文件系统呈现为一种树状结构&#xff0c;以根目录/为最顶层&#xff0c;其下分布着各种不同的子目录&#xff0c;每个目录都有其特定的用途和功能。下面是Linux目录结构的详细介绍&#xff1a; 1. 根目录 / 根目录是整个文件系统的基础。所有的目录和文件都从这里开始…

LeetCode刷题13:回溯+剪枝解决216.组合总和 III

找出所有相加之和为 n 的 k 个数的组合&#xff0c;且满足下列条件&#xff1a; 只使用数字1到9每个数字 最多使用一次 返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次&#xff0c;组合可以以任何顺序返回。 示例 1: 输入: k 3, n 7 输出: [[1,2,4]] 解…

阿里云c8i服务器CPU性能、架构及费用测评

阿里云第八代云服务器ECS计算型c8i实例&#xff0c;CPU采用Intel Xeon Emerald Rapids或者Intel Xeon Sapphire Rapids&#xff0c;主频不低于2.7 GHz&#xff0c;全核睿频3.2&#xff0c;阿里云百科aliyunbaike.com分享阿里云c8i服务器CPU处理器型号、存储、网络、安全、使用场…

子域名收集

目录 1、OneForAll 2、利用Google的搜索 3、fofa 4、使用在线查询网站查询 5、利用ip反查 6、Layer子域名挖掘机 7、JSFinder 用法 在进行渗透的过程中有一个很重要的工作就是信息收集&#xff0c;而信息收集中的子域名收集是很重要的一项工作&#xff0c;在本篇中我会给大…

绝地求生:【PC】2024年1月商店更新

亲爱的玩家朋友们&#xff0c;大家好&#xff01; 欢迎大家来到闲游盒2024年首次商店更新&#xff01; 我们在1月商店更新中准备了全新生存通行证&#xff1a;龙腾&#xff0c;彩色烟雾皮肤&#xff0c;地狱天使 VS 天堂恶魔系列皮肤&#xff0c;相信大家一定会喜欢~ 实用腰带…

Linux操作系统——进程控制(三) 进程程序替换

前言 目前我们接触到我们所创建的所有的子进程&#xff0c;它执行的代码都是父进程代码的一部分&#xff01;那么如果我们想让子进程执行新的程序呢&#xff1f;&#xff1f;&#xff1f;执行全新的代码和访问全新的数据&#xff0c;不在和父进程有瓜葛&#xff0c;我们该怎么…

一文详解向量数据库Milvus Cloud动态 Schema

在数据库中&#xff0c;Schema 常有&#xff0c;而动态 Schema 不常有。 例如&#xff0c;SQL 数据库有预定义的 Schema&#xff0c;但这些 Schema 通常都不能修改&#xff0c;用户只有在创建时才能定义 Schema。Schema 的作用是告诉数据库使用者所希望的表结构&#xff0c;确…

如何利用 NFTScan Portfolio 功能分析钱包 NFT 持仓

随着 NFT 市场的扩大和投资者的增加&#xff0c;追踪和管理大量 NFT 资产正变得越来越复杂&#xff0c;无论是新手还是资深投资者&#xff0c;都需要借助实时的 NFT 数据作为判断依据。因此&#xff0c;一个能够全面分析 NFT 钱包持仓的工具就显得尤为重要。帮助投资者掌握自身…

bootstrap搭建一个简单的官网案例附代码

bootstrap搭建一个简单的官网案例附代码 效果常用属性完整代码 效果 大概的效果如下 主要都是用bootstrap的代码实现的 网站是照着 b站视频做的 查看视频教程 建议自己先看一遍文档再跟着视频写&#xff0c;不然可能看不懂 bootstarp中文文档 logo是从别人的站上扒的有点不太协…

阿里巴巴提出AnyText:首个解决多语言视觉文本生成的工作

基于扩散模型的文本到图像在最近取得了令人瞩目的成就。尽管当前的图像合成技术已经非常先进&#xff0c;能够以高保真度生成图像&#xff0c;但当关注生成图像中的文本区域时&#xff0c;往往可能会暴露问题&#xff0c;因为合成文本通常包含模糊、不可读或不正确的字符&#…

firewalld高级配置

IP伪装与端口转发 在互联网发展初期&#xff0c;设计者们并没有想到互联网会发展到现在这个空前繁荣的阶段&#xff0c;所以&#xff0c;设 计的Pv4地址空间只有32位.但是随着互联网的发展&#xff0c;P地址变得严重缺乏&#xff0c;并且地址分配不均匀&#xff0c; 所以就在原…

设计模式-规格模式

设计模式专栏 模式介绍模式特点应用场景规格模式和策略模式的区别和联系代码示例Java实现规格模式Python实现规格模式 规格模式在spring中的应用 模式介绍 规格模式&#xff08;Specification Pattern&#xff09;是一种行为设计模式&#xff0c;其目的是将业务规则封装成可重…

AIGC实战——改进循环神经网络

AIGC实战——改进循环神经网络 0. 前言1. 堆叠循环网络2. 门控制循环单元3. 双向单元相关链接 0. 前言 我们已经学习了如何训练长短期记忆网络 (Long Short-Term Memory Network, LSTM) 模型&#xff0c;以学习使用给定风格生成文本&#xff0c;接下来&#xff0c;我们将学习如…

OceanBase原生分布式数据库

1.历史背景 在Java Web项目中&#xff0c;常常使用免费开源的MySQL数据库存储业务数据&#xff0c;按业界经验MySQL单库超过多大数据体量&#xff0c;或单表超过几百万条数据后就会出现查询变慢的情况&#xff0c;单实例数据库只能扩展物理资源(CPU、内存)&#xff0c;来提升查…

vivado 工程管理

管理项目 打开项目 当项目打开时&#xff0c;Vivado IDE会从项目已关闭。项目状态包括当前源文件顺序、已禁用和已启用 源文件、活动约束文件和目标约束文件&#xff0c;以及合成、模拟和实现运行。要打开项目&#xff0c;请使用以下方法之一&#xff1a; •在“入门”页面…