【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.rhkb.cn/news/235255.html

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

相关文章

华为面经总结

为了帮助大家更好的应对面试&#xff0c;我整理了往年华为校招面试的题目&#xff0c;供大家参考~ 面经1 技术一面 自我介绍说下项目中的难点volatile和synchronized的区别&#xff0c; 问的比较细大顶堆小顶堆怎么删除根节点CSRF攻击是什么&#xff0c;怎么预防线程通信方式…

CMU15-445-Spring-2023-Project #2 - B+Tree

前置知识&#xff1a;参考上一篇博文 CMU15-445-Spring-2023-Project #2 - 前置知识&#xff08;lec07-010&#xff09; CHECKPOINT #1 Task #1 - BTree Pages 实现三个page class来存储B树的数据。 BTree Page internal page和leaf page继承的基类&#xff0c;只包含两个…

最实用的 8 个免费 Android 数据恢复软件

如果您正在寻找最好的免费 Android 数据恢复软件&#xff0c;那就不用再犹豫了&#xff0c;因为我已经列出了最好的软件。不可否认&#xff0c;智能手机和平板电脑等 Android 设备正在与技术一起发展。与以前相比&#xff0c;它们也更加融入了我们的日常生活。 Android 智能手…

Flask+Bootstrap4案例[有源码]

文章目录 Flask案例开源地址简介一、环境搭建1.1 canda常用命令1.2 创建虚拟环境1.3 安装flask1.4 导入flaskdemo项目 二、项目配置2.1 开启DEBUG2.2 配置数据库连接参数2.3 安装项目依赖2.4 修改flaskdemo中的错误 三、组件3.1 flash3.2 pagination3.3 table3.4 nav3.5 form3.…

冠军团队!第二届百度搜索创新大赛AI方案

Datawhale干货 作者&#xff1a;李柯辰&#xff0c;Datawhale成员 写在前面 大家好&#xff0c;我们是2023年第二届百度搜索创新大赛 赛道三——AI应用设计赛道的冠军团队——“肝到凌晨”&#xff0c;很高兴能与大家分享我们这次比赛的经验&#xff0c;同时也希望以后有机会可…

前端-基础 表格标签 - 相关属性详解

目录 相关属性 &#xff1a; align 属性 &#xff1a; border 属性 &#xff1a; cellpadding 属性 &#xff1a; cellspacing 属性 &#xff1a; width 属性 &#xff1a; height 属性 &#xff1a; 首先&#xff0c;需要声明的是 表格标签这部分属性&…

springboot 房屋租赁系统

spring boot mysql mybatis 前台后端

揭秘LoRA与QLoRA:百次实验告诉你如何微调LLM!

原文链接&#xff1a;揭秘LoRA与QLoRA&#xff1a;百次实验告诉你如何微调LLM&#xff01;​​​​​​​ LoRA&#xff08;低秩适应&#xff09;是目前应用最广泛、参数效率最高的自定义大型语言模型&#xff08;LLM&#xff09;微调技术之一。本文不仅介绍了使用QLoRA节省内存…

用判断对齐大语言模型

1、写作动机&#xff1a; 目前的从反馈中学习方法仅仅使用判断来促使LLMs产生更好的响应&#xff0c;然后将其作为新的示范用于监督训练。这种对判断的间接利用受到无法从错误中学习的限制&#xff0c;这是从反馈中学习的核心精神&#xff0c;并受到LLMs的改进能力的制约。 2…

科学和统计分析软件GraphPad Prism mac介绍说明

GraphPad Prism for Mac是一款科学和统计分析软件&#xff0c;旨在帮助研究者、科学家和学生更轻松地处理和可视化数据。 GraphPad Prism for Mac是一款功能强大、易于使用的科学和统计分析软件&#xff0c;适用于各种类型的数据处理和可视化需求。无论您是进行基础研究、临床试…

给自己创建的GPTs添加Action(查天气)

前言 在这篇文章中&#xff0c;我将分享如何利用ChatGPT 4.0辅助论文写作的技巧&#xff0c;并根据网上的资料和最新的研究补充更多好用的咒语技巧。 GPT4的官方售价是每月20美元&#xff0c;很多人并不是天天用GPT&#xff0c;只是偶尔用一下。 如果调用官方的GPT4接口&…

Django的数据库模型的CharField字段的max_length参数与中文字符数的关系探索(参数max_length的单位是字符个数还是字节数?)

01-清理干净之前的数据库迁移信息 02-根据setting.py中的信息删除掉之前建立的数据库 03-删除之后重新创建数据库 04-models.py中创建数据库模型 from django.db import modelsclass User(models.Model):username models.CharField(max_length4)email models.EmailField(uni…

接口测试管理续集

今天应大家需要&#xff0c;接着谈app端数据返回层面的用例设计方法。第二部分给大家安利一个“接口管理平台”&#xff0c;以帮助大家解决接口文档维护、接口测试数据Mock、接口自动化测试等问题。希望对小伙伴们有用。 言归正传&#xff0c;进入今天的话题。 一、用例设计 …

深度学习算法应用实战 | 利用 CLIP 模型进行“零样本图像分类”

文章目录 1. 零样本图像分类简介1.1 什么是零样本图像分类?1.2 通俗一点的解释 2. 模型原理图3. 环境配置4. 代码实战5. Gradio前端页面5.1 什么是 Gradio ? 6 进阶操作7. 总结 1. 零样本图像分类简介 1.1 什么是零样本图像分类? “零样本图像分类”&#xff08;Zero-shot …

自学Python,需要注意哪些?

为什么要学习Python&#xff1f; 在学习Python之前&#xff0c;你不要担心自己没基础或“脑子笨”&#xff0c;我始终认为&#xff0c;只要你想学并为之努力&#xff0c;就能学好&#xff0c;就能用Python去做很多事情。在这个喧嚣的时代&#xff0c;很多技术或概念会不断兴起…

配置安装nginx

目录 一、yum安装 1.进入nginx官网 nginx.org 2、进入下载列表 以主线版为例 3、服务器安装工具包集合 4、设置 yum 存储库 5、配置成功后&#xff0c;默认情况下&#xff0c;使用稳定的 nginx 包的存储库。如果要使用主线 nginx 包&#xff0c;需要运行以下命令&#xf…

Asp .Net Web应用程序(.Net Framework4.8)网站发布到IIS

开启IIS 如果已开启跳过这步 打开控制面板-程序 打开IIS 发布Web程序&#xff08;.Net Framework 4.8 web网页&#xff09; 进入IIS管理器新建一个应用池 新建一个网站 网站创建完毕 为文件夹添加访问权限 如果不添加访问权限&#xff0c;运行时将会得到如下错误 设置权限 勾…

PHP开发日志 ━━ 不同方法判断某个数组中是否存在指定的键名,测试哪种方法效率高

我们可以用isset($arr[a]) 或者 array_key_exists(a, $arr) 来判断a键名是否存在与$arr数组。 那么这两种方式哪个运行速度快呢&#xff1f; 不多废话了&#xff0c;现在我们写一段代码来测试一下&#xff1a; $array [a > 1, b > 2, c > 3];$start microtime(tru…

YOLOv8优化策略:轻量化改进 | 华为Ghostnet,超越谷歌MobileNet | CVPR2020

🚀🚀🚀本文改进:Ghost bottleneck为堆叠Ghost模块 ,与YOLOV8建立轻量C2f_GhostBottleneck 🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1.Ghostnet介绍 论文: https://arxiv.org/pdf/1911.11907.…

Logstash:迁移数据到 Elasticsearch

在生产环境中&#xff0c;不使用 Apache Kafka 等流平台进行数据迁移并不是一个好的做法。 在这篇文章中&#xff0c;我们将详细探讨 Apache Kafka 和 Logstash 的关系。 但首先让我们简单了解一下 Apache Kafka 的含义。 Apache Kafka 是分布式流平台&#xff0c;擅长实时数据…