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

Foreign-Memory Access API外部内存API

引入API,使Java程序能够安全有效地访问Java堆之外的外部内存

发展历史:

JEP 383: Foreign-Memory Access API (Second Incubator)   java15

JEP 393: Foreign-Memory Access API (Third Incubator) java16

JEP 389: Foreign Linker API (Incubator) java16

JEP 412: Foreign Function & Memory API (Incubator)  java17

JEP 419: Foreign Function & Memory API (Second Incubator) java18

JEP 424: Foreign Function & Memory API (Preview)  java19

JEP 434: Foreign Function & Memory API (Second Preview) java20

JEP 442: Foreign Function & Memory API (Third Preview) java21

JEP 454: Foreign Function & Memory API java22

JEP 472: Prepare to Restrict the Use of JNI java24

对外内存访问API引入了三个主要的抽象:MemorySegment、MemoryAddress和MemoryLayout。

MemorySegment用于对具有给定空间和时间边界的连续内存区域进行建模。MemoryAddress可以看作是段内的偏移。最后,MemoryLayout是对内存段内容的程序化描述。
内存段可以从各种来源创建,例如本机内存缓冲区、Java数组和字节缓冲区(直接或基于堆)。例如,可以按如下方式创建本机内存段:

try(MemorySegment段=MemorySegment.reallocateNative(100)){
...
}

这将创建一个与大小为100字节的本机内存缓冲区关联的内存段。

Memory segments在空间上是有界限的,它们有下限和上限。任何试图使用该段访问这些边界之外的内存的尝试都将导致异常。正如使用try with resource构造所证明,segments在时间上也是有界的,它们被创建、使用,然后在不再使用时关闭。关闭一个段总是一个显式的操作,可能会导致额外的副作用,例如与该段相关的内存的释放。任何访问已关闭内存段的尝试都会导致异常。因此空间和时间安全检查对于保证内存访问API的安全性至关重要,来保证没有硬JVM崩溃。

通过获取内存访问变量句柄,可以实现对与段关联的内存的解引用。这些特殊的var句柄至少有一个MemoryAddress类型的强制访问坐标,这是发生解引用的地址。它们是使用MemoryHandles类中的工厂方法获得的。例如,要设置本机段的元素,我们可以使用内存访问var句柄,如下所示

VarHandle intHandle = MemoryHandles.varHandle(int.class,
ByteOrder.nativeOrder());

try (MemorySegment segment = MemorySegment.allocateNative(100)) {
MemoryAddress base = segment.baseAddress();
for (int i = 0; i < 25; i++) {
intHandle.set(base.addOffset(i * 4), i);
}
}

内存访问var句柄还可以获取一个或多个long类型的额外访问坐标,以支持更复杂的寻址方案,如多维索引访问。这种内存访问var句柄通常是通过调用一个或多个组合子方法获得的,这些方法也在MemoryHandles类中定义。例如,设置本机段元素的一种更直接的方法是通过索引内存访问句柄,其构造如下:

VarHandle intHandle = MemoryHandles.varHandle(int.class, 
ByteOrder.nativeOrder());
VarHandle intElemHandle = MemoryHandles.withStride(intHandle, 4);

try (MemorySegment segment = MemorySegment.allocateNative(100)) {
MemoryAddress base = segment.baseAddress();
for (int i = 0; i < 25; i++) {
intElemHandle.set(base, (long) i, i);
}
}

这有效地允许对原本平坦的内存缓冲区进行丰富的多维寻址。
为了增强API的表达能力,并减少对显式数字计算(如上面示例中的计算)的需要,可以使用MemoryLayout API以编程方式描述内存段的内容。例如,上述示例中使用的本机内存段的布局可以按以下方式描述:

SequenceLayout intArrayLayout= MemoryLayout.ofSequence(25,MemoryLayout.ofValueBits(32,ByteOrder.nativeOrder()));

这创建了一个序列内存布局,其中给定的元素布局(32位值)重复25次。一旦我们有了内存布局,我们就可以摆脱代码中的所有手动数值计算,并简化所需内存访问var句柄的创建,如下例所示:

SequenceLayout intArrayLayout= MemoryLayout.ofSequence(25,MemoryLayout.ofValueBits(32,ByteOrder.nativeOrder()));
VarHandle intElemHandle= intArrayLayout.varHandle(int.class,PathElement.sequenceElement());
try (MemorySegment segment = MemorySegment.allocateNative(intArrayLayout)) {
MemoryAddress base = segment.baseAddress();
for (int i = 0; i < intArrayLayout.elementCount().getAsLong(); i++) {
intElemHandle.set(base, (long) i, i);
}
}

在这个例子中,布局实例通过创建布局路径来驱动内存访问var句柄的创建,该路径用于从复杂的布局表达式中选择嵌套布局。布局实例还驱动本机内存段的分配,该分配基于从布局中导出的大小和对齐信息。前面示例中的循环常量已被序列布局的元素计数替换。
外部存储器访问API最初将作为一个孵化模块提供,名为jdk.incubator.foreign,在一个同名的包中。

http://www.dtcms.com/a/335670.html

相关文章:

  • 混沌工程(Chaos engineering):系统韧性保障之道
  • 计算机网络 HTTPS 全流程
  • p5.js 3D 形状 “预制工厂“——buildGeometry ()
  • 【位运算】查询子数组最大异或值|2693
  • 图灵完备(Turing Complete)免安装中文版
  • 关于pygsp引发的一系列问题和实例小demo
  • ​​Vue 3 开发速成手册
  • 裸机框架:按键模组
  • macos 安装nodepad++ (教程+安装包+报错后的解决方法)
  • AI证书怎么选
  • 交叉编译 手动安装 SQLite 库 移植ARM
  • 基于Vue + Node能源采购系统的设计与实现/基于express的能源管理系统#node.js
  • JavaScript 性能优化实战大纲
  • 记SpringBoot3.x + Thymeleaf 项目实现(MVC架构模式)
  • .NET 中的延迟初始化:Lazy<T> 与LazyInitializer
  • 【Java后端】MyBatis-Plus 原理解析
  • Unity进阶--C#补充知识点--【Unity跨平台的原理】了解.Net
  • Linux | i.MX6ULL网络通信-套字节 UDP(第十八章)
  • 【牛客刷题】后缀子串字母统计:O(n)高效算法详解
  • python实现梅尔频率倒谱系数(MFCC) 除了傅里叶变换和离散余弦变换
  • 数学建模 15 逻辑回归与随机森林
  • 大上墨水屏显示器Paperlike253 Mac 特别版 使用体会
  • MySQL数据库初识
  • 黑马java八股文全集
  • AUTOSAR ARXML介绍
  • 数据结构(排序篇)——七大排序算法奇幻之旅:从扑克牌到百亿数据的魔法整理术
  • C++编程实战:高效解决算法与数据结构问题
  • 【CV 目标检测】Fast RCNN模型②——算法流程
  • 【递归、搜索与回溯算法】记忆化搜索
  • 图解希尔排序C语言实现