当前位置: 首页 > news >正文

Java Native Interface 使用指南

我们知道Java本身的实现,很大一部分是用C++写的。实际上,Java也允许我们和原生平台的代码进行交互。

Java定义了一个接口规范,就叫做Java Native Interface,通过这个接口规范,我们就可以让Java代码运行原生平台的代码。

首先写一个Java的Class1:

public class HelloJNI {static {System.loadLibrary("hello"); // Load native library at runtime// hello.dll (Windows) or libhello.so (Unixes)}// Declare a native method sayHello() that receives nothing and returns voidprivate native void sayHello();// Test Driverpublic static void main(String[] args) {new HelloJNI().sayHello();  // invoke the native method}
}

从上面的代码,我们看到一些平常写Java代码的时候不常看见的东西,首先是这个:

 System.loadLibrary("hello");

这个System.loadLibrary方法可以用来调用平台的原生库。然后是这个:

private native void sayHello();

这个native关键字意味着这个代码的实现是原生平台实现,而不是Java代码。因此我们要做一个hello库,提供这个sayHello方法。

接下来我们用javah命令生成.h文件:

$ ls HelloJNI.java
HelloJNI.java
$ javah HelloJNI
$ ls *.h
HelloJNI.h

我们得到了HelloJNI.h文件,它的内容是根据HelloJNI.java生成的,我们看看里面的内容:

/* 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:    sayHello* Signature: ()V*/
JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *, jobject);#ifdef __cplusplus
}
#endif
#endif

可以看到上面的文件里自动生成了JNI接口规范的一些约定代码。比如jni.h这个是由JDK提供的,我们稍后要引用。还有sayHello对应的C/C++的方法是Java_HelloJNI_sayHello,这个命名方式可以看出来是Java_ClassName_MethodName,这个也是JNI的约定。

接下来我们写一个HelloJNI.c来实现这个HelloJNI.h

#include <jni.h>
#include <stdio.h>
#include "HelloJNI.h"// Implementation of native method sayHello() of HelloJNI class
JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject thisObj) {printf("Hello World!\n");return;
}

这个代码就非常简单,就是实现了Java_HelloJNI_sayHello,功能就是printf("Hello World!\n");。我们编译这个代码:

$ c++ -c -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin" HelloJNI.c

注意我是在MacOS上编译,所以引用的是MacOS的JDK的include目录,此外MacOS的内核名叫darwin,你如果用Linux系统,你的JDK的include目录里应该有一个linux目录,对应上面的darwin目录。

这两个-I主要是为了引用JNI相关的库文件:

$ ls $JAVA_HOME/include/jni*
/Library/Java/JavaVirtualMachines/jdk1.8.0_66.jdk/Contents/Home/include/jni.h
$ ls $JAVA_HOME/include/darwin/jni*
/Library/Java/JavaVirtualMachines/jdk1.8.0_66.jdk/Contents/Home/include/darwin/jni_md.h

这两个.h文件是必须的。编译完成后,我们就得到了object文件:

$ ls *.o
HelloJNI.o

nm命令看一下这个object file里面的符号:

$ nm HelloJNI.o
0000000000000000 T _Java_HelloJNI_sayHelloU _printf

可以看到包含的的methods。我们要把这个object文件链接成library,在MacOS下命令如下:

$ c++ -dynamiclib -o libhello.jnilib HelloJNI.o

这样我们就得到了Java可以调用的libhello.jnilib

$ ls *.jnilib
libhello.jnilib

我们在Java代码里写的是System.loadLibrary("hello"),但是这里的library名字叫做libhello,前面多了lib,这是一种命名约定。

如果你在Linux系统下,生成library的命令不太一样,需要用下面的命令生成.so文件,也就是shared library文件:

cc -shared -fpic -o libhello.so -I/usr/java/include -I/usr/java/include/linux HelloJNI.c

接下来就是编译Java代码:

$ javac HelloJNI.java

我们得到class文件:

$ ls *.class
HelloJNI.class

此时目录里应该有我们的library还有class文件:

$ ls *.class *.jnilib
HelloJNI.class  libhello.jnilib

此时我们可以使用java命令运行HelloJNI.class

$ java HelloJNI
Hello World!

可以看到我们这个Hello World!字符串是来自于native method的Java_HelloJNI_sayHello里面的printf。我们的Java代码与原生平台进行了交互。

参考资料:

  1. https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.htm

相关文章:

Java Native Interface 使用指南

我们知道Java本身的实现&#xff0c;很大一部分是用C写的。实际上&#xff0c;Java也允许我们和原生平台的代码进行交互。 Java定义了一个接口规范&#xff0c;就叫做Java Native Interface&#xff0c;通过这个接口规范&#xff0c;我们就可以让Java代码运行原生平台的代码。…...

代码随想录算法训练营第三十九天 | 62.不同路径、63. 不同路径 II、343. 整数拆分、96.不同的二叉搜索树

62.不同路径 题目链接&#xff1a;https://leetcode.cn/problems/unique-paths/ 文档讲解&#xff1a;https://programmercarl.com/0062.%E4%B8%8D%E5%90%8C%E8%B7%AF%E5%BE… 视频讲解&#xff1a;https://www.bilibili.com/video/BV1ve4y1x7Eu/ 思路 确定dp数组以及下标的含…...

C/C++函数指针、C#委托是什么?

函数指针 #include<stdio.h>//声明函数指针 typedef int(*Calc)(int a, int b); int Add(int a, int b) {return a b; } int Sub(int a, int b) {return a - b; }int main() {Calc funcPoint1 &Add;Calc funcPoint2 &Sub;int x 120;int y 140;int z 0;z …...

红队攻防渗透技术实战流程:组件安全:JacksonFastJsonXStream

红队攻防渗透实战 1. 组件安全1.1 J2EE-组件Jackson-本地demo&CVE1.1.1 代码执行 (CVE-2020-8840)1.1.2 代码执行(CVE-2020-35728)1.2 J2EE-组件FastJson-本地demo&CVE1.2.1 FastJson <= 1.2.241.2.2 FastJson <= 1.2.471.2.3 FastJson <= 1.2.801.3 J2EE-组…...

Perl 语言学习进阶

一、如何深入 要深入学习Perl语言的库和框架&#xff0c;可以按照以下步骤进行&#xff1a; 了解Perl的核心模块&#xff1a;Perl有许多核心模块&#xff0c;它们提供了许多常用的功能。了解这些模块的功能和用法是深入学习Perl的第一步。一些常用的核心模块包括&#xff1a;S…...

LangGraph实战:从零分阶打造人工智能航空客服助手

❝ 通过本指南&#xff0c;你将学习构建一个专为航空公司设计的客服助手&#xff0c;它将协助用户查询旅行信息并规划行程。在此过程中&#xff0c;你将掌握如何利用LangGraph的中断机制、检查点技术以及更为复杂的状态管理功能&#xff0c;来优化你的助手工具&#xff0c;同时…...

R可视化:R语言基础图形合集

R语言基础图形合集 欢迎大家关注全网生信学习者系列&#xff1a; WX公zhong号&#xff1a;生信学习者Xiao hong书&#xff1a;生信学习者知hu&#xff1a;生信学习者CDSN&#xff1a;生信学习者2 基础图形可视化 数据分析的图形可视化是了解数据分布、波动和相关性等属性必…...

mysql导入sql文件失败及解决措施

1.报错找不到表 1.1 原因 表格创建失败&#xff0c;编码问题mysql8相较于mysql5出现了新的编码集 1.2解决办法&#xff1a; 使用vscode打开sql文件ctrlh&#xff0c;批量替换&#xff0c;替换到你所安装mysql支持的编码集。 2.timestmp没有设置默认值 Error occured at:20…...

JS:获取鼠标点击位置

一、获取鼠标在目标元素中的点击位置 getClickPos.ts: export const getClickPos (e: MouseEvent) > {return {x: e.offsetX,y: e.offsetY,}; };二、获取鼠标在页面中的点击位置 getClickPos.ts: export const getPageClickPos (e: MouseEvent) > {return {x: e.pa…...

使用开源的zip.cpp和unzip.cpp实现压缩包的创建与解压(附源码)

目录 1、使用场景 2、压缩包的创建 3、压缩包的解压 4、CloseZipZ和CloseZipU两接口的区别...

npm 异常:peer eslint@“>=1.6.0 <7.0.0“ from eslint-loader@2.2.1

node 用16版本 npm install npm6.14.15 -g将版本降级到6...

Docker|了解容器镜像层(2)

引言 容器非常神奇。它们允许简单的进程表现得像虚拟机。在这种优雅的底层是一组模式和实践&#xff0c;最终使一切运作起来。在设计的根本是层。层是存储和分发容器化文件系统内容的基本方式。这种设计既出人意料地简单&#xff0c;同时又非常强大。在今天的帖子[1]中&#xf…...

使用Python爬取temu商品与评论信息

【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python与爬虫领域研究与开发工作&#xff01; 【&…...

mybatis学习--自定义映射resultMap

1.1、resultMap处理字段和属性的映射关系 如果字段名和实体类中的属性名不一致的情况下&#xff0c;可以通过resultMap设置自定义映射。 常规写法 /***根据id查询员工信息* param empId* return*/ Emp getEmpByEmpId(Param("empId") Integer empId);<select id…...

Elasticsearch之写入原理以及调优

1、ES 的写入过程 1.1 ES支持四种对文档的数据写操作 create&#xff1a;如果在PUT数据的时候当前数据已经存在&#xff0c;则数据会被覆盖&#xff0c;如果在PUT的时候加上操作类型create&#xff0c;此时如果数据已存在则会返回失败&#xff0c;因为已经强制指定了操作类型…...

python中装饰器的用法

最近发现装饰器是一个非常有意思的东西&#xff0c;很高级&#xff01; 允许你在不修改函数或类的源代码的情况下&#xff0c;为它们添加额外的功能或修改它们的行为。装饰器本质上是一个接受函数作为参数的可调用对象&#xff08;通常是函数或类&#xff09;&#xff0c;并返…...

php实现一个简单的MySQL分页

一、案例演示&#xff1a; 二、php 代码 <?php $servername "localhost"; // MySQL服务器名称或IP地址 $username "root"; // MySQL用户名 $password "123456"; // MySQL密码 $dbname "test"; // 要连接…...

算法训练营day23补签

题目1&#xff1a;530. 二叉搜索树的最小绝对差 - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int reslut INT_MAX;TreeNode* pre NULL;void trackingback(TreeNode* node) {if(node NULL) return;trackingback(node->left);if(pre ! NULL) {reslut…...

国密SM2JS加密后端解密

1.前端加密 前端加密开源库 sm-crypto 1.1 传统web,下载 sm-crypto 进行打包为 dist/sm2.js 相关打包命令 npm install --save sm-crypto npm install npm run prepublish在web页面引用打包后的文件 <script type"text/javascript" src"<%path %>…...

Cheat Engine.exe修改植物大战僵尸阳光与冷却

Cheat Engine.exe修改植物大战僵尸阳光与冷却 打开Cheat Engine.exe和植物大战僵尸&#xff0c;点CE中文件下面红框位置&#xff0c;选择植物大战僵尸&#xff0c;点击打开 修改冷却&#xff1a; 等冷却完毕&#xff0c;首次扫描0安放植物&#xff0c;再次扫描变动值等冷却完…...

FPGA Multiboot翻车实录:从XDC配置到ICAPE2,我的W25Q128分区血泪史与避坑指南

FPGA Multiboot实战&#xff1a;从配置陷阱到Flash分区优化的全流程解析 第一次在量产产品中实现FPGA远程更新功能时&#xff0c;我盯着实验室里突然变砖的开发板&#xff0c;后背渗出一层冷汗。原本以为按照官方文档配置就能万无一失&#xff0c;没想到Multiboot这个看似简单的…...

一文搞懂Agent三大核心技术:Function Calling、MCP、A2A,小白也能轻松收藏学习!

本文详细解析了AI Agent的三大核心技术&#xff1a;Function Calling、MCP和A2A。Function Calling使AI能够主动获取外部信息&#xff0c;MCP为工具接入提供了标准化接口&#xff0c;而A2A则实现了多智能体之间的协作。通过这三个技术的演进&#xff0c;AI Agent的能力从点对点…...

IP5306电源芯片的‘怪脾气’:实测开机半分钟就休眠?手把手教你两个硬件调试技巧

IP5306电源芯片实战调试&#xff1a;破解自动休眠难题的硬件级方案 实验室里&#xff0c;示波器屏幕上那条本该稳定的电压线突然跌落至零&#xff0c;系统再次陷入休眠——这已经是今天第七次重现IP5306芯片的"怪脾气"。作为一款广泛应用于移动电源的高集成度SOC&…...

从DVWA存储型XSS看Web安全:开发者常踩的坑与Impossible级别的启示

从DVWA存储型XSS看Web安全&#xff1a;开发者常踩的坑与Impossible级别的启示 在Web应用开发中&#xff0c;安全漏洞就像隐藏在代码中的定时炸弹&#xff0c;而存储型XSS&#xff08;跨站脚本攻击&#xff09;无疑是其中最具破坏力的一种。不同于反射型XSS的一次性攻击&#xf…...

PP实战指南:ECN工程变更在物料计划中的关键应用与系统操作解析

1. ECN工程变更的核心价值与业务场景 第一次接触ECN&#xff08;Engineering Change Notice&#xff09;是在2015年负责汽车零部件项目时&#xff0c;当时产线因为一个螺丝规格变更导致全线停产8小时。这个惨痛教训让我深刻理解到&#xff0c;工程变更绝不是简单的技术文档更新…...

C++的std--ranges算法自定义比较器与等价关系在集合操作中的运用

C20引入的std::ranges库为算法操作带来了革命性改进&#xff0c;其中自定义比较器与等价关系的灵活运用&#xff0c;显著提升了集合操作的表达能力。通过精确控制元素间的比较逻辑&#xff0c;开发者能够实现更复杂的业务需求&#xff0c;例如处理自定义对象集合或实现非标准排…...

会用AI的人,早已拉开职场差距!全岗位工作范式重构进行时

AI深度融入职场&#xff0c;正在改写工作的底层逻辑&#xff0c;会用AI的从业者&#xff0c;已在工作效率与职业发展上形成明显优势。从开发人员的研发流程&#xff0c;到方案人员的工作模式&#xff0c;再到各行各业的基础岗位&#xff0c;AI不再只是简单的效率工具&#xff0…...

嵌入式轻量级3D数学库mmath:面向MCU的定点/浮点向量矩阵运算

1. 项目概述mmath是一个专为嵌入式系统设计的轻量级三维数学库&#xff0c;其核心目标是在资源受限的 MCU&#xff08;如 Cortex-M0/M3/M4&#xff09;上提供高效、无浮点依赖&#xff08;可选&#xff09;、内存占用可控的 3D 向量、矩阵、四元数及空间变换运算能力。与通用桌…...

JetBrains推出AI智能体管理平台Central

为了帮助开发者控制日益增长的AI编程智能体队伍&#xff0c;JetBrains正在推出JetBrains Central&#xff0c;这是一个面向团队的智能体开发平台&#xff0c;用于管理和维持对这些智能体的监督。JetBrains Central的早期访问计划将于2026年第二季度开始&#xff0c;将有限量的设…...

全平台网络资源下载神器:一键获取微信视频号、抖音、QQ音乐等热门内容

全平台网络资源下载神器&#xff1a;一键获取微信视频号、抖音、QQ音乐等热门内容 【免费下载链接】res-downloader 资源下载器、网络资源嗅探&#xff0c;支持微信视频号下载、网页抖音无水印下载、网页快手无水印视频下载、酷狗音乐下载等网络资源拦截下载! 项目地址: http…...