jdk21的外部函数和内存API(官方翻译)

1、jdk21:   引入一个 API,通过该 API,Java 程序可以与 Java 运行时之外的代码和数据进行互操作。通过有效地调用外部函数(即JVM外部的代码)和安全地访问外部内存(即不由JVM管理的内存),API使Java程序能够调用本机库并处理本机数据,而不会像JNI那样脆弱和危险。这是一个预览版 API。

2、jdk21引入了MemorySegment内存段,和Arena竞技场

3、jdk21为什么要这么做? 答:java开发人员在访问一种重要的非Java资源时依然很困难

4、使用关键字创建的对象存储在 JVM 的中,当不再需要时,它们将受到垃圾回收。但是,垃圾收集的成本和不可预测性对于性能关键型库(如Tensorflow,Ignite,Lucene和Netty)来说是不可接受的。他们需要将数据存储在堆外,存储在堆外内存中,这些内存是他们自己分配和解除分配的。对堆外内存的访问还允许通过将文件直接映射到内存中来序列化和反序列化数据,例如 mmapnew

5、java平台历来提供两个用来访问堆外内存的api:

ByteBuffer Api: 提供直接字节缓冲区,这些缓冲区是由固定大小的堆外内存区域支持的 Java 对象。但是,区域的最大大小限制为 2 GB,读取和写入内存的方法基本且容易出错,仅提供对基元值的索引访问。更严重的是,仅当缓冲区对象被垃圾回收时,才会释放支持直接字节缓冲区的内存,这是开发人员无法控制的。缺乏对及时释放的支持使得 API 不适合使用 Java 进行系统编程。ByteBuffer

6、sun.misc.Unsafe Api:提供对堆内存的低级别访问,该访问也适用于堆外内存。使用速度很快(因为它的内存访问操作是由 JVM 固有的),允许巨大的堆外区域(理论上高达 16 EB),并提供对释放的细粒度控制(因为可以随时调用)。但是,此编程模型很弱,因为它给了开发人员太多的控制。长时间运行的服务器应用程序中的库将随着时间的推移分配堆外内存的多个区域并与之交互;一个区域中的数据将指向另一个区域中的数据,并且必须以正确的顺序释放区域,否则悬而未决的指针将导致释放后使用错误。缺乏对安全释放的支持使得 API 不适合用 Java 进行系统编程。UnsafeUnsafe::freeMemoryUnsafe

7、总之,复杂的客户端应该得到一个 API,它可以分配、操作和共享堆外内存,具有与堆内存相同的流动性和安全性。这样的 API 应该在可预测的释放需求与防止可能导致 JVM 崩溃或更糟糕的静默内存损坏的不合时宜的释放之间取得平衡。

8、外文函数

8.1、JNI从java1.1开始就支持调用本机函数(外部函数),但是不足点也多

Java API(方法)、派生自 Java API 的 C 头文件以及调用感兴趣的本机库的 C 实现。Java 开发人员必须跨多个工具链工作,以保持依赖于平台的工件同步,这在本机库快速发展时尤其繁重。native

JNI 只能与用语言(通常是 C 和 C++)编写的库进行互操作,这些库使用构建 JVM 的操作系统和 CPU 的调用约定。方法不能用于调用使用不同约定的语言编写的函数。native

JNI 不协调 Java 类型系统与 C 类型系统。Java 中的聚合数据用对象表示,但 C 中的聚合数据用结构表示,因此传递给方法的任何 Java 对象都必须由本机代码费力地解压缩。例如,考虑 Java 中的记录类:将对象传递给方法将需要本机代码使用 JNI 的 C API 从对象中提取字段(例如,和)。因此,Java 开发人员有时会将数据平展为单个对象(例如,字节数组或直接字节缓冲区),但更常见的是,由于通过 JNI 传递 Java 对象很慢,他们使用 API 分配堆外内存并将其地址作为方法传递给方法 - 这使得 Java 代码非常不安全!

9、内存段是由位于堆外或堆上的连续内存区域支持的抽象,分段的时间边界由用于分配分段的竞技场确定。

最简单的竞技场是全球竞技场,它提供了无限的生命周期:它永远活着。

自动竞技场提供有限的生存期:可以访问由自动竞技场分配的段,直到 JVM 的垃圾回收器检测到内存段不可访问,此时支持该段的内存区域被解除分配。

受限竞技场提供有限且确定的生存期:从客户端打开竞技场到客户端关闭竞技场,它一直处于活动状态。在受限竞技场中分配的内存段只能在竞技场关闭之前访问

本人先举个MemorySegment内存段,和Arena竞技场的例子吧

自由竞技场

package org.example.ass;import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.VarHandle;import static java.lang.foreign.ValueLayout.JAVA_DOUBLE;class WindowsSharedMemory{public static void main(String[] args) {MemorySegment point= Arena.ofAuto().allocate(8*2);point.set(JAVA_DOUBLE,0,3d);point.set(JAVA_DOUBLE,8,4d);System.out.println(point.get(JAVA_DOUBLE, 0));}

这里我使用的是自由竞技场来创建的,也就是说当这个MemorySegment不可达时,该内存区域被解除分配

这里要注意一点,我是在0号位置set  3d占了8个字节,取的时候,就是在0号位置,取8个字节,这个JAVA_DOUBLE是所占的单位,因为double一般是8个字节

受限竞技场(错误代码),我之前说什么了?在受限竞技场中分配的内存段只能在竞技场关闭之前访问,我故意出个错误的代码

package org.example.ass;import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.VarHandle;import static java.lang.foreign.ValueLayout.JAVA_DOUBLE;class WindowsSharedMemory{public static void main(String[] args) {MemorySegment point=null;try ( Arena allocate= Arena.ofConfined()){point = allocate.allocate(8 * 2);point.set(JAVA_DOUBLE,0,3d);point.set(JAVA_DOUBLE,8,4d);}System.out.println(point.get(JAVA_DOUBLE, 0));}

全球竞技场我就不提例子了,因为太简单了,这个竞技场永远存活,把上面的例子中的.ofConfined()改为.global()就好了,运行结果:

没错又是报错,不过你看一下报错信息:试图关闭一个不可关闭的会话

这个是由于try ( 这里面运行完会自动调用关闭的那个方法){} 造成的,我就是故意举出错误例子,让你们深刻理解

10、为了应对c语言的结构体,例如:

PointPointPoint.xPoint.y

struct Point {int x;int y;
} pts[10];

那我们如何在java的内存段里面搞呢?

openjdk引入了一个类,叫内存布局Memorylayout

package org.example.ass;import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.VarHandle;import static java.lang.foreign.MemoryLayout.sequenceLayout;
import static java.lang.foreign.ValueLayout.JAVA_DOUBLE;class WindowsSharedMemory{public static void main(String[] args) {WindowsSharedMemory windowsSharedMemory=new WindowsSharedMemory();windowsSharedMemory.play();}public void play(){SequenceLayout POINT_2D =sequenceLayout(10, MemoryLayout.structLayout(JAVA_DOUBLE.withName("x"),JAVA_DOUBLE.withName("y")));VarHandle xHandle    // (MemorySegment, long) -> int= POINT_2D.varHandle(MemoryLayout.PathElement.sequenceElement(),MemoryLayout.PathElement.groupElement("x"));VarHandle yHandle    // (MemorySegment, long) -> int= POINT_2D.varHandle(MemoryLayout.PathElement.sequenceElement(),MemoryLayout.PathElement.groupElement("y"));MemorySegment segment = Arena.ofAuto().allocate(POINT_2D);for (int i = 0; i < POINT_2D.elementCount(); i++) {xHandle.set(segment,/* index */ (long) i,/* value to write */ i); // xyHandle.set(segment,/* index */ (long) i,/* value to write */ i); // y}for (int i = 0; i < POINT_2D.elementCount(); i++) {System.out.println(xHandle.get(segment,/* index */ (long) i)); // xSystem.out.println(yHandle.get(segment,/* index */ (long) i)); // y}}

运行结果:

区段分配器

当客户端使用堆外内存时,内存分配通常是一个瓶颈。因此,FFM API 包括一个分段分配器抽象,用于定义分配和初始化内存段的操作。为方便起见,Arena 类实现了该接口,以便可以使用 arenas 来分配本机段。换句话说,是灵活分配和及时释放堆外内存的“一站式商店”:SegmentAllocatorArena

package org.example.ass;import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.VarHandle;import static java.lang.foreign.MemoryLayout.sequenceLayout;
import static java.lang.foreign.ValueLayout.JAVA_DOUBLE;
import static java.lang.foreign.ValueLayout.JAVA_INT;class WindowsSharedMemory{public static void main(String[] args) {try (Arena offHeap = Arena.ofConfined()) {MemorySegment nativeArray  = offHeap.allocateArray(ValueLayout.JAVA_INT,0, 1, 2, 3, 4, 5, 6, 7, 8, 9);MemorySegment nativeString = offHeap.allocateUtf8String("Hello!");System.out.println(nativeArray.get(JAVA_INT, 0));System.out.println(nativeArray.get(JAVA_INT, 4));System.out.println(nativeArray.get(JAVA_INT, 8));System.out.println(nativeArray.get(JAVA_INT, 12));System.out.println(nativeString.getUtf8String(0));}}

运行结果:

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

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

相关文章

统计学习方法 感知机

文章目录 统计学习方法 感知机模型定义学习策略学习算法原始算法对偶算法 学习算法的收敛性 统计学习方法 感知机 读李航的《统计学习方法》时&#xff0c;关于感知机的笔记。 感知机&#xff08;perceptron&#xff09;是一种二元分类的线性分类模型&#xff0c;属于判别模型…

大模型,重构自动驾驶

文&#xff5c;刘俊宏 编&#xff5c;王一粟 大模型如何重构自动驾驶&#xff1f;答案已经逐渐露出水面。 “在大数据、大模型为特征&#xff0c;以数据驱动为开发模式的自动驾驶3.0时代&#xff0c;自动驾驶大模型将在车端、云端上实现一个统一的端到端的平台管理。”毫末智…

uni-app:实现时钟自走(动态时钟效果)

效果 核心代码 使用钩子函数 mounted()&#xff0c;设置定时器&#xff0c;是指每秒都要去执行时间的获取&#xff0c;以至于实现时间自走的效果 mounted() { this.updateTime(); // 初始化时间 setInterval(this.updateTime, 1000); // 每秒更新时间 }, 自定义方法…

NodeMCU ESP8266 读取按键外部输入信号详解(图文并茂)

NodeMCU ESP8266 读取按键外部输入信号教程&#xff08;图文并茂&#xff09; 文章目录 NodeMCU ESP8266 读取按键外部输入信号教程&#xff08;图文并茂&#xff09;前言按键输入常用接口pinModedigitalRead 示例代码结论 前言 ESP8266如何检测外部信号的输入&#xff0c;通常…

Java封装:面向对象的三大特性之一

&#x1f451;专栏内容&#xff1a;Java⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、封装的概念二、访问修饰限定符三、包1、包的概念2、导入包中的类3、常见的包 嗨&#xff01;前面我们简单的认识了一下什么…

常用的设计模式以及操作Redis、MySQL数据库、各种MQ、数据类型转换的方法

文章目录 &#x1f31f; 如何优雅地写出高质量的Java代码&#x1f34a; 设计模式&#x1f389; 单例模式&#x1f389; 工厂模式&#x1f389; 观察者模式 &#x1f34a; 操作Redis&#x1f389; 连接Redis&#x1f389; 存储数据&#x1f389; 获取数据&#x1f389; 删除数据…

Java注解处理器APT

注解处理器介绍 什么是APT&#xff1f; 在JDK6的时候引入了JSR269的标准&#xff0c;即APT&#xff08;Annotation Processing Tool&#xff09;&#xff0c;用于在编译时处理源代码中的注解&#xff0c;从而生成额外的代码、配置文件或其他资源。与传统的运行时反射相比&…

深入探索Sharding JDBC:分库分表的利器

随着互联网应用的不断发展和用户量的不断增加&#xff0c;传统的数据库在应对高并发和大数据量的场景下面临着巨大的挑战。为了解决这一问题&#xff0c;分库分表成为了一个非常流行的方案。分库分表主流的技术包括MyCat和Sharding JDBC。我们来通过一张图来了解这两者有什么区…

C语言——二周目——程序的翻译与执行环境

一、程序环境 对于一个C语言程序的实现&#xff0c;整个过程一般存在两个不同的环境&#xff0c;分别是翻译环境与执行环境。在翻译环境中&#xff0c;我们所写的源代码经过一系列处理被转换成为可执行的机器指令&#xff1b;在执行环境中&#xff0c;会实际执行代码。 整个程序…

Open3D(C++) 最小二乘拟合平面(拉格朗日乘子法)

目录 一、算法原理二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。 一、算法原理 设拟合出的平面方程为: a x + b y + c

手写redux的connect方法, 使用了subscribe获取最新数据

一. 公共方法文件 1. connect文件 import React, { useState } from "react"; import MyContext from "./MyContext"; import _ from "lodash";// 模拟react-redux的 connect高阶函数 const connect (mapStateToProps, mapDispatchToProps) &…

数学建模——最优连接(基于最小支撑树)

一、概念 1、图的生成树 由图G(V,E)的生成子图G1(V,E1)(E1是E的子集&#xff09;是一棵树&#xff0c;则称该树为图G的生成树&#xff08;支撑树&#xff09;&#xff0c;简称G的树。图G有支撑树的充分必要条件为图G连通。 2、最小生成树问题 连通图G(V,E)&#xff0c;每条边…

STM32串口

前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 目前已经学习了GPIO的输入输出&#xff0c;但是没有完整的显示信息&#xff0c;最便宜的显示就是串口。 000 -111 AVR单片机 已经学会过了&#xff0c; 提示&#xff1a;以下是本篇文章正文内容&#x…

Servlet的生命周期

2023.10.18 WEB容器创建的Servlet对象&#xff0c;这些Servlet对象都会被放到一个集合当中&#xff08;HashMap&#xff09;&#xff0c;这个集合当中存储了Servlet对象和请求路径之间的关系 。只有放到这个HashMap集合中的Servlet才能够被WEB容器管理&#xff0c;自己new的Ser…

《视觉 SLAM 十四讲》V2 第 10 讲 后端优化2 简化BA 【位姿图】

文章目录 第10讲 后端210.1 滑动窗口滤波 和 优化10.1.2 滑动窗口法 10.2 位姿图10.3 实践&#xff1a; 位姿图优化本讲 CMakeLists.txt 10.3.1 g2o 原生位姿图 【Code】10.3.2 李代数上的位姿优化 【Code】 习题10题1 【没推完】 LaTex 第10讲 后端2 滑动窗口优化 位姿图优化…

最新!两步 永久禁止谷歌浏览器 Google Chrome 自动更新

先放效果图&#xff1a; CSDN这个问题最火的大哥的用了没用 像他这样连浏览器都打不开 为什么要禁止chrome自动更新 看到很多搞笑的大哥&#xff0c;说为啥要禁止&#xff1b; 我觉得最大的原因就是chromedriver跟不上chrome的自动更新&#xff0c;导致我们做selenium爬虫的…

CentOS 7 安装 MySQL 8

一、卸载MariaDB MariaDB是MySQL 的一个分支&#xff0c;完全兼容MySQL&#xff0c;包括API和命令行&#xff0c;使之能轻松成为MySQL的代替品。 1、查看版本&#xff08;如果有就卸载&#xff09; rpm -qa|grep mariadbrpm -e --nodeps 文件名 二、下载mysql 1、进入 /usr/…

中枢听觉处理障碍的行为干预方法

作者&#xff1a;听觉健康 在数十年前&#xff0c;中枢听觉处理障碍(CAPD)的研究已经引起了多学科的关注。1937年&#xff0c;Samuel Orton提出某些儿童的学习障碍与不能有效利用听觉有关。Myklebust是提出“中枢性听力障碍”引起儿童语言学习障碍的先驱者之一。二十世纪五十年…

C# Winform编程(7)文件处理技术

文件处理技术 System.IO命名空间System.IO命名空间常用的类System.IO命名空间常用的枚举 File类的常用方法FileInfo类的常用方法File类和FileInfo类的区别文件夹类Directory的常用方法 System.IO命名空间 System.IO命名空间常用的类 类说明File提供用于创建&#xff0c;复制&…

【数之道 08】走进“卷积神经网络“,了解图像识别背后的原理

卷积神经网络 CNN模型的架构Cnn 的流程第一步 提取图片特征提取特征的计算规则 第二步 最大池化第三步 扁平化处理第四步 数据条录入全连接隐藏层 b站视频 CNN模型的架构 图片由像素点组成&#xff0c;最终成像效果由背后像素的颜色数值所决定的 有这样的一个66的区域&#x…