java直接内存的读写操作

Java多线程内存读写 —— 内存屏障的理解 在现代计算机中,CPU往往都是多核的,而由于每个CPU Core中都有自己的高速缓存Cache,因此就会造成内存数据读写的不一致性,表现为指令乱序与不可见性问题。为此,java为了统一物理世界中的计算机组成架构,提出了JMM内存模型,并抽象了LoadLoad,StoreStore,LoadStore,StoreLoad四个内存屏障指令来应对不同CPU的体系。本文先介绍下多核CPU体系下,并发编程需要克服的问题,然后再介绍下Java的内存屏障各自的含义,并举例说明对应的场景。 阅读详情

前言

在之前已经讲过了一些关于直接内存的知识,相对于的就会去思考,直接内存是怎么去使用的。
首先说明下,一般不会直接这样去用直接内存,这个例子只能当做一个例子去使用,netty里面有许多非常经典的使用方式,可以参考下。

代码

这里没有什么好说的先上代码吧。
public class BufferTest4 {

    private static final int BUFFER = 10 * 1024 * 1024;//10m

    //直接分配本地内存空间
    private static ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER);

    public static void main(String[] args) throws IOException {

        Scanner scanner = new Scanner(System.in);
        System.out.println("请求指示:");
        scanner.next();
        List<TestObj> bigObj = new ArrayList<TestObj>();
        for (int n = 0; n < 600000; n++) {
            bigObj.add(new TestObj(n));
        }

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        Hessian2Output output = new Hessian2Output(bos);
        output.writeObject(bigObj);
        output.flush();
        byte[] date = bos.toByteArray();
        bos.close();
        byteBuffer.put(date);

        System.out.println("对象存入到直接内存!");

        scanner.next();
        byteBuffer.flip();
        byte[] b = new byte[byteBuffer.limit()];
        int i = 0;
        while (byteBuffer.hasRemaining()) {

            b[i] = byteBuffer.get();
            i++;
        }

        ByteArrayInputStream bis = new ByteArrayInputStream(b);
        Hessian2Input input = new Hessian2Input(bis);
        List<TestObj> objRead = (List<TestObj>) input.readObject();

        System.out.println("读取直接内存内的对象!" + objRead);
        scanner.next();

        System.out.println("直接内存开始释放!");
        byteBuffer = null;
        System.gc();

        scanner.next();
    }
}

直接内存的申请这里就不多说,一般并且下我们会先将序列化好的对象放入到内存中

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        // Hessian2的序列化方式
        Hessian2Output output = new Hessian2Output(bos);
        output.writeObject(bigObj);
        output.flush();
        byte[] date = bos.toByteArray();
        bos.close();
        //放入内存
        byteBuffer.put(date);
如果需要读取出来,就需要先将标志位反转,然后开始读取,最后还是需要反序列化
  
      // 反转标志位
        byteBuffer.flip();
        byte[] b = new byte[byteBuffer.limit()];
        int i = 0;
        // 判断是否还有未读的
        while (byteBuffer.hasRemaining()) {
            b[i] = byteBuffer.get();
            i++;
        }
        // 反序列化
        ByteArrayInputStream bis = new ByteArrayInputStream(b);
        Hessian2Input input = new Hessian2Input(bis);
        List<TestObj> objRead = (List<TestObj>) input.readObject();

扩展说明

在上面的例子中,申请的内存是10m,如果生成的对象比申请的直接内存大会怎么样?可以将申请的内存改为3m,运行代码的时候直接报如下错误。

请求指示:
1
Exception in thread "main" java.nio.BufferOverflowException
    at java.nio.DirectByteBuffer.put(DirectByteBuffer.java:360)
    at java.nio.ByteBuffer.put(ByteBuffer.java:859)
为什么说,上面的例子不是一个确定的用法,上面的例子最后还是将用到了jvm里面的内存,并没有利用到直接内存的优点。不需要中系统内存复制到jvm内存中,这个才是直接内存的有点。
下面写一个例子测试下直接内存的读取
public class ByteBufferDemo1 {

    public static void main(String[] args) throws IOException {

        long start =  System.currentTimeMillis();
        String filepath = "/Users/*/Downloads/2.1.0.501.zip" //1g左右;
        FileInputStream fis = new FileInputStream(filepath);
        FileChannel fci = fis.getChannel();


        // 把刚读取的信息写到一个新的文件中
        String outfilepath = "/Users/*/code/2.1.0.501.zip";
        FileOutputStream fos = new FileOutputStream(outfilepath);
        FileChannel fco = fos.getChannel();


        // 使用allocateDirect,而不是allocate
        ByteBuffer buffer = ByteBuffer.allocateDirect(512*1024*1024);
        while (true) {
            buffer.clear();
            int r = fci.read(buffer);
            if (r == -1) break;
            buffer.flip();
            fco.write(buffer);
        }


        long end =  System.currentTimeMillis();


        System.out.println((end-start));
    }
}
使用 ByteBuffer.allocateDirect
第一次
1409
Process finished with exit code 0

第二次
1401
Process finished with exit code 0

第三次
1372
Process finished with exit code 0

使用ByteBuffer.allocate

第一次
2087
Process finished with exit code 0

第二次
2159
Process finished with exit code 0

第三次
2219
Process finished with exit code 0
稍微快一点。
基于集成运放心电放大器设计(原创) 原创作者:einyboy or alert 最近在看美剧《危机边缘》关于边缘科学的案件,科技控可以看一下,但建议不在吃东西的时候看。想像力是创造的思想源头,动手能力则是创造的车床。 自认为是没有想像力的那类,只能发挥动手能力了。 心电测量简介 图1 心电极接线图 如图1心电测试一般使用3个心电极进行测量,各个电极的说明如下: RA: Right Arm缩写,右手电极 LA: L... 阅读详情

相关推荐

Windows 11下ROS2 Humble与PyCharm无缝集成实战(避坑指南+完整配置流程)

本文详细介绍了在Windows 11系统下如何实现ROS2 Humble与PyCharm的无缝集成,包括环境准备、ROS2 Humble安装、PyCharm配置以及C++与Qt5混合开发的实战技巧。通过避坑指南和完整配置流程,帮助开发者高效搭建稳定的机器人开发环境,特别适合Windows平台的ROS2开发者。

weixin_28710999的博客 366

Java中使用Redis(即学即用)

一、为什么需要用Redis? Redis(Remote Dictionary Server),一个基于内存的高性能key-value数据库。针对关系型数据库性能瓶颈来设计的,处理关系型数据库不擅长做的业务场景。Redis 多用于项目的高速缓存,可以让项目性能更好。 Redis的应用场景 二、安装Redis 1、下面提供其中一个版本的Redis: 链接:https://pan.baidu.com/s/1Z3QRpdMzUyPh8ODZJDgGEA 提取码:j8vl 复制这段内容后打开百度...

心有谦谦结 9568

检测头篇 | 手把手教你如何去更换YOLOv8的检测头为ASFF_Detect

自适应空间特征融合(ASFF)的主要原理旨在解决单次检测器中不同尺度特征的不一致性问题。具体来说,ASFF通过动态调整来自不同尺度特征金字塔层的特征贡献,确保每个检测对象的特征表示是一致且最优的。本文所做出的改进是将YOLOv8的检测头更换为ASFF_Detect。🌈

小哥谈 2496

Redis——java代码读写redis

一,简单Jedis读写      Jedis jedis=new Jedis("127.0.0.1",6379);//连接的是我本地的服务 System.out.println("成功连接到服务器=="); /*存取string类型*/ jedis.set("name", "lhc"); model.addAttribute("name",jedis.get("name"))

我们的征途是星辰大海 1万+

基于投影法实现扫描文件的光学字符分割——Matlab实现

投影法是指将原图像沿着某个特定的方向进行投影,得到投影线上的像素点的个数或像素值总和,从而可以得到该方向上物体的轮廓信息。对于字符分割,我们可以将图像进行水平和垂直两个方向的投影,从而得到字符之间的分割线。在OCR技术中,字符分割是非常重要的一步骤,因为字符之间的分割对字符识别的准确性有很大的影响。通过对投影值的判断,可以求出字符之间的分割线,这里我们根据垂直方向上的投影值进行判断,选取一个阈值进行筛选即可。使用sum()函数分别计算出水平和垂直方向上的投影值,得到每一行和每一列的投影值。

TechGlide的博客 581

黑猫带你学eMMC协议第33篇:eMMC CQE功能介绍——一种模仿UFS命令队列的发送机制

本文详细介绍了eMMC协议中的Command Queuing Engine (CQE)及其相关功能。CQE是eMMC 5.1版本引入的新特性,旨在通过硬件处理命令队列,简化软件代码的编写。文章首先介绍了CQE的基本概念,包括其与Host Controller Interface (HCI)的区别,以及CQE如何通过Task Descriptor List (TDL)管理任务。接着,文章详细描述了CQE如何发送命令和数据给eMMC,并解释了Task Descriptor和Transfer Descriptor

黑猫奥利奥的博客 980

使用java来写一个游戏外挂-内存修改程序(辅助-开篇)

关于如何使用java来写一个内存修改程序(辅助-开篇)

qq_44495732的博客 9489

YOLOv11改进 | 融合改进篇 | 利用尺度统一检测头DynamicHead融合P2增加小目标检测层(让小目标无所遁形)

本文给大家带来的最新改进机制是针对性的改进,针对于小目标检测增加P2层针对于大目标检测增加P6层利用DynamicHead(原版本一比一复现,全网独一份,不同于网上魔改版本)进行检测,其中我们增加P2层其拥有更高的分辨率,这使得模型能够更好地捕捉到小尺寸目标的细节。我们增加P6层是一个较低分辨率但具有更大感受野的特征层。对于大尺寸目标,这意味着模型可以更有效地捕捉到整体的结构信息。在这些的基础上我们配合DynamicHead可以使模型根据不同尺寸的目标动态调整其检测策略,进一步提升模型的精度。

Snu77的博客 3941

JAVA直接内存(堆外内存)

本篇主要讲解如何使用直接内存(堆外内存),并按照下面的步骤进行说明: 1 相关背景-->读写操作-->关键属性-->读写实践-->扩展-->参考说明 希望对想使用直接内存的朋友,提供点快捷的参考。 数据类型 下面这些,都是在使用DirectBuffer中必备的一些常识,暂作了解吧!如果想要深入理解,可以看看下面参考的那些博客

点点的博客 2600

ResNet改进(7):添加 SK注意力机制

实现 SK 注意力机制。

2401_82355416的博客 730

Pointnet++改进90:2025最新改进模块-EVA模块

本教程提出了一种改进PointNet++特征提取模块的方法,通过在PointNetSetAbstraction模块中加入NAMAttention注意力机制,显著提升了模型性能。具体改进包括:1)新建eva.py文件,实现了包含SDLSKA、CKS等关键组件的EVA模块;2)在pointnet2_utils.py中添加Conv和PointNetSetAbstractionAttention类,整合注意力机制;3)修改pointnet2_sem_seg.py模型结构。这种改进方法降低了实现难度,同时保持了33F

AIcurator的博客 360

Jvm(15),运行时数据---直接内存

  假如你现在还在为自己的技术担忧,假如你现在想提升自己的工资,假如你想在职场上获得更多的话语权,假如你想顺利的度过35岁这个魔咒,假如你想体验BAT的工作环境,那么现在请我们一起开启提升技术之旅吧,详情请点击http://106.12.206.16:8080/qingruihappy/index.html   直接内存并不是虚拟机运行时数据区的一部分,也不是Java 虚拟机规范中农定义的内...

weixin_34228662的博客 121

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Java直接(堆外)内存使用详解

本篇主要讲解如何使用直接内存(堆外内存),并按照下面的步骤进行说明: 相关背景-->读写操作-->关键属性-->读写实践-->扩展-->参考说明 希望对想使用直接内存的朋友,提供点快捷的参考。 数据类型 下面这些,都是在使用DirectBuffer中必备的一些常识,暂作了解吧!如果想要深入理解,可以看看下面参考的那些博客。 基本类型长度 在Java中有很多的基本类型,...

weixin_30485379的博客 194

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

JVM直接内存

象作为这块内存的引用进行操作。结论: 在数据量提升时,直接内存相比非直接内的申请,有很严重的性能问题。直接内存申请空间耗费更高的性能,当频繁申请到一定量时尤为明显。读写的性能要优于普通的堆内存,在多次读写操作的情况下差异明显。操作上,在频繁的读写时 会有显著的性能提升。直接内存 和 堆内存的 分配空间比较。直接内存 和 堆内存的 读写性能比较。次分配操作时,直接内存 分配耗时。次分配操作时,直接内存 分配耗时。次分配操作时,堆内存 分配耗时。次分配操作时,堆内存 分配耗时。次读写操作时,直接内存读写耗时。

2301_77822280的博客 659

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Java NIO 编程之 ByteBuffer 基础(ByteBuffer 概述、创建 ByteBuffer、基础读写操作、核心属性与模式切换)

Java NIO 编程之 ByteBuffer 基础(ByteBuffer 概述、创建 ByteBuffer、基础读写操作、核心属性与模式切换)

weixin_52173250的博客 1171

10.1 直接内存 - 直接内存

直接内存 概述 不是虚拟机运行时数据区的一部分, 也不是《Java虚拟机规范》中定义的内存区域。 直接内存是在Java堆外的、直接向系统申请的内存区间。 来源于NIO,通过存在堆中的DirectByteBuf fer操作Native内存 通常,访问直接内存的速度会优于Java堆。即读写性能高。 因此出于性能考虑,读写频繁的场合可能会考虑使用直接内存。 Java的NIO库允许Java程序使用直接内存,用于数据缓冲区 也可能导致OutOfMemoryError异常 由于直接内存在Java堆外,因

u013559614的博客 99

直接内存JVM

直接内存概述 概述 不是虚拟机运行时数据区的一部分, 也不是虚拟机规范中定义的内存区域。 直接内存是再java堆外的、直接向系统申请的内存空间。 来源于NIO, 通过存在堆中的DirectByteBuffer操作Native内存。 通常, 访问直接内存的速度会优于java堆。 即读写性能高。 出于性能考虑, 读写频繁的场合可能会考虑使用直接内存。 java 的NIO库允许java程序使用直接内u才能, 用于数据缓冲区。 有了NIO时, 操作系统划出的直接缓存区, 可以被java代码直接访问, 只有一份,

dogs的博客 159

第十一章 直接内存(Direct Memory)

读写文件,需要与磁盘交互,需要由用户态切换到内核态。在内核态时,需要内存如下图的操作。这里需要两份内存存储重复数据,效率低。使用 NIO 时,如下图。操作系统划出的直接缓存区可以被 Java 代码直接访问,只有一份。NIO 适合对大文件的读写操作。

dingd1234的博客 427

Java堆外内存之五:堆外内存管理类ByteBuffer

本篇主要讲解如何使用直接内存(堆外内存),并按照下面的步骤进行说明: 相关背景--&gt;读写操作--&gt;关键属性--&gt;读写实践--&gt;扩展--&gt;参考说明 希望对想使用直接内存的朋友,提供点快捷的参考。 数据类型 下面这些,都是在使用DirectBuffer中必备的一些常识,暂作了解吧! 基本类型长度 在Java中有很多的基本类型,比如: ...

weixin_33923148的博客 100

JVM-直接内存

NIO,使用native 函数库直接分配堆外内存,不经过JVM 内存直接访问系统物理内存的类——DirectBuffer。DirectBuffer 类继承自ByteBuffer,但和普通的ByteBuffer 不同,普通的ByteBuffer 仍在JVM 堆上分配内存,其最大内存受到最大堆内存的限制;而DirectBuffer 直接分配在物理内存中,并不占用堆空间,其可申请的最大内存受操作系统限制。 堆内存比较: 直接内存申请空间耗费更高的性能,当频繁申请到一定量时尤为明显 直接内存IO 读写的性能要优于

siyuanwai的博客 134
上一篇: JVM与直接内存分析
下一篇: 基于tensorflow的ResNet50V2网络识别动物
sinom21
博客等级 码龄19年 22粉丝 33原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sinom21

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值