当前位置: 首页 > 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;再次扫描变动值等冷却完…...

Fulling框架:构建完整AI智能体的工程化实践指南

1. 项目概述&#xff1a;从“FullAgent”到“Fulling”的智能体进化之路最近在开源社区里&#xff0c;一个名为“Fulling”的项目引起了我的注意。它隶属于“FullAgent”这个组织&#xff0c;名字本身就很有意思。“Fulling”这个词&#xff0c;在英语里有“使…丰满、充实”的…...

Zotero插件市场TOP1新势力:Perplexity Connector v2.3正式发布,支持LLM上下文感知文献溯源,仅限前500名开发者早鸟激活

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;Perplexity Zotero整合方案全景概览 Perplexity 作为新一代 AI 驱动的研究型搜索引擎&#xff0c;其核心优势在于实时引用溯源与上下文感知问答&#xff1b;Zotero 则是学术工作者广泛采用的开源文献管…...

uniapp中获取APP应用签名信息

/*** 获取应用签名MD5* returns {Promise<unknown>}*/ function getAppSignatureMD5() {return new Promise((resolve) > {// 1. 环境检查if (typeof plus "undefined" || uni.getSystemInfoSync().platform ! "android") {resolve(null);return…...

Dify工作流构建指南:从业务需求到可运行AI应用的全流程解析

1. 项目概述&#xff1a;从业务需求到可运行工作流的全栈构建器如果你正在使用 Dify 这类低代码 AI 应用开发平台&#xff0c;大概率遇到过这样的困境&#xff1a;脑子里有一个清晰的业务想法&#xff0c;比如“我想做一个能自动处理客服工单并生成摘要的机器人”&#xff0c;但…...

将Taotoken作为内部AI中台统一对接各类客户端工具

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 将Taotoken作为内部AI中台统一对接各类客户端工具 设想一个中型研发团队&#xff0c;内部已经引入了Claude Code、OpenClaw等多种A…...

电源完整性设计:电容模型、去耦策略与测量验证实战解析

1. 电容与去耦&#xff1a;从概念到实战的深度解析上周我们聊了聊去耦电容在电源完整性设计中的一些基本概念和时机选择&#xff0c;算是开了个头。这周咱们继续深入&#xff0c;把这块硬骨头啃得更透一些。很多工程师&#xff0c;尤其是刚入行的朋友&#xff0c;常常觉得电容选…...

基于Vercel AI SDK与Next.js的聊天机器人模板开发实战

1. 项目概述&#xff1a;一个开箱即用的AI聊天机器人模板 如果你正在寻找一个能快速启动、功能齐全且易于定制的AI聊天机器人项目&#xff0c;那么Vercel官方出品的这个Chatbot模板绝对值得你花时间研究。它不是一个简单的Demo&#xff0c;而是一个生产就绪的、基于现代Web技术…...

从零搭建VGG16:深入解析网络架构与PyTorch实战

1. VGG16网络架构解析 VGG16作为卷积神经网络发展史上的里程碑&#xff0c;其核心设计理念至今仍影响着现代深度学习模型。我第一次接触这个网络时&#xff0c;被它简洁优雅的结构深深吸引——全部使用33小卷积核堆叠&#xff0c;配合22最大池化&#xff0c;这种设计就像用乐高…...

乔布斯产品哲学对硬件工程师的启示:从参数到体验的转变

1. 项目概述&#xff1a;一次对乔布斯遗产的技术性致敬2011年10月6日&#xff0c;当史蒂夫乔布斯逝世的消息传来&#xff0c;整个科技界陷入了一种复杂的情绪。作为一名长期在电子工程与消费电子领域工作的人&#xff0c;我的感受尤为深刻。那天&#xff0c;我和我的同事们&…...

Windows下Python包管理权限踩坑实录:从WinError 5到WinError 32的完整解决流程

Windows下Python包管理权限问题深度解析&#xff1a;从WinError 5到WinError 32的实战指南 作为一名长期在Windows平台进行Python开发的工程师&#xff0c;我深刻理解文件权限问题带来的困扰。特别是当你在紧急项目交付前夜&#xff0c;突然遭遇PermissionError: [WinError 5]或…...