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

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...