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

news2024/11/19 5:36:22

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); // x
            yHandle.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)); // x
            System.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.coloradmin.cn/o/1117200.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一种基于HTTPS实现的Web账号登录Linux桌面系统的实现方案

问题由来 客户需求计划列入支持第三方帐号系统&#xff0c;包括Web账号。需求来源是用户想要用它们的帐号直接登录Linux Deepin操作系统。一个失败的实现方案是用户以较小的成本改造帐号管理系统发布HTTP服务&#xff0c;我们开发一个PAM模块与Web服务器交互&#xff0c;数据格…

基于天鹰优化的BP神经网络(分类应用) - 附代码

基于天鹰优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于天鹰优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.天鹰优化BP神经网络3.1 BP神经网络参数设置3.2 天鹰算法应用 4.测试结果&#xff1a;5.M…

2023年【广东省安全员A证第四批(主要负责人)】考试试卷及广东省安全员A证第四批(主要负责人)模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 广东省安全员A证第四批&#xff08;主要负责人&#xff09;考试试卷根据新广东省安全员A证第四批&#xff08;主要负责人&#xff09;考试大纲要求&#xff0c;安全生产模拟考试一点通将广东省安全员A证第四批&#x…

小程序之后台数据动态交互及WXS的使用 (5)

⭐⭐ 小程序专栏&#xff1a;小程序开发专栏 ⭐⭐ 个人主页&#xff1a;个人主页 目录 一.前言 二.后台数据交互 2.1 准备工作 2.1 前台首页数据连接&#xff1a; 三.WXS的使用 今天就分享到这啦&#xff01;&#xff01;&#xff01; 一.前言 本文章续前面的文章的前端界面…

【JUC系列-15】深入理解CompletableFuture的基本使用

JUC系列整体栏目 内容链接地址【一】深入理解JMM内存模型的底层实现原理https://zhenghuisheng.blog.csdn.net/article/details/132400429【二】深入理解CAS底层原理和基本使用https://blog.csdn.net/zhenghuishengq/article/details/132478786【三】熟练掌握Atomic原子系列基本…

2023 10月8日 至 10 月16日学习总结

1.做的题目 [RootersCTF2019]I_&#xff1c;3_Flask_双层小牛堡的博客-CSDN博客 [NCTF2019]SQLi regexp 盲注-CSDN博客 [网鼎杯 2018]Comment git泄露 / 恢复 二次注入 .DS_Store bash_history文件查看-CSDN博客 PHP LFI 利用临时文件Getshell_双层小牛堡的博客-CSDN博客 …

《动手学深度学习 Pytorch版》 9.7 序列到序列学习(seq2seq)

循环神经网络编码器使用长度可变的序列作为输入&#xff0c;将其编码到循环神经网络编码器固定形状的隐状态中。 为了连续生成输出序列的词元&#xff0c;独立的循环神经网络解码器是基于输入序列的编码信息和输出序列已经看见的或者生成的词元来预测下一个词元。 要点&#x…

关于使用 vxe-table 时设置了 show-overflow tooltip 不展示的问题(Dialog 组件和 table 同时使用)

众所周知&#xff0c;vxe-table 是可以支撑万级数据渲染的表格组件&#xff0c;本质上还是用了虚拟滚动的实现。之前一直知道vxe-table, 但是基本没有机会用的上这个组件&#xff0c;最近在开发埋点数据的统计&#xff0c;后端一次性返回了上千条数据&#xff0c;elementui 的 …

【Shell】环境变量 自定义变量 特殊变量

Shell变量&#xff1a;环境变量 目标 1、理解什么是系统环境变量&#xff1f; 2、掌握常用的系统环境变量都有哪些&#xff1f; Shell变量的介绍 变量用于存储管理临时的数据, 这些数据都是在运行内存中的. 变量类型 系统环境变量 自定义变量 特殊符号变量 系统环境变…

golang查看CPU使用率与内存及源码中的//go:指令

golang查看CPU使用率与内存 1 psutil 1.1 概念与应用场景 psutil是业内一个用于监控OS资源的软件包&#xff0c;目前已经多种语言&#xff0c;包括但不限于Python、Go。 gopsutil是 Python 工具库psutil 的 Golang 移植版&#xff0c;可以帮助我们方便地获取各种系统和硬件信…

基于Java的实验室设备管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

如何在电脑上设置新的蓝牙耳机

本文介绍如何将蓝牙耳机连接到Windows或Mac电脑。 如何在Windows上设置新的蓝牙耳机 蓝牙耳机的设置过程因平台而异&#xff0c;但以下是Windows 11的步骤&#xff1a; 1、选择“开始”&#xff0c;然后在搜索框中输入蓝牙&#xff0c;以显示蓝牙和其他设备。 2、选择添加设…

【LeetCode:2316. 统计无向图中无法互相到达点对数 | BFS + 乘法原理】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

施密特正交化

相信大家在平时的期末考试中一定少不了对某某向量组执行标准正交化类型的题目。今天我们从这个题目入手&#xff0c;说明这个如何执行施密特正交化&#xff0c;以及为什么要进行正交化。 一、例子 例子&#xff1a;设 a 1 [ 1 2 − 1 ] a_1\begin{bmatrix}1\\2\\-1\end{bmat…

阿里妈妈Union Lab全量公测,你会用吗?

Union Lab是一种智能化的选品推荐、推广内容创作工具&#xff0c;它内置了大语言模型&#xff08;LLMs&#xff09;&#xff0c;使得选品、推广更加智能和简单。通过联盟底层货品服务&#xff0c;Union Lab可以实现智能化货品发现、分析、选品、投放、创意生产&#xff0c;基于…

嵌入式mqtt总线架构方案mosquitto+paho

一 mqtt通信模型 MQTT 协议提供一对多的消息发布&#xff0c;可以降低应用程序的耦合性&#xff0c;用户只需要编写极少量的应用代码就能完成一对多的消息发布与订阅&#xff0c;该协议是基于<客户端-服务器>模型&#xff0c;在协议中主要有三种身份&#xff1a;发布者&…

力扣第37题 解数独 c++ 难~ 回溯

题目 37. 解数独 困难 相关标签 数组 哈希表 回溯 矩阵 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫…

基于Java的文物管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

GRASP 、SOLID 与 GoF 设计模式

一、GRASP GRASP&#xff1a;通用职责分配软件设计模式(General Responsibility Assignment Software Patterns)&#xff0c;其主要思想是基于单一职责设计软件对象。 思考软件对象设计以及大型构件的流行方式是&#xff0c;考虑其职责、角色和协作。这是被称为职责驱动设计&a…

C++:无法查找或打开 PDB 文件?? 如何解决呢?以及产生原因是什么?

C:无法查找或打开 PDB 文件?? 如何解决呢&#xff1f;以及产生原因是什么&#xff1f; 前言解决办法原因 前言 最近博主在写C时&#xff0c;明明代码都正确&#xff0c;但编译失败。查看原因后发现显示&#xff1a;无法查找或打开 PDB 文件。&#xff08;先介绍解决办法&…