首页
学习
活动
专区
圈层
工具
发布
    • 综合排序
    • 最热优先
    • 最新优先
    时间不限
  • 来自专栏xingoo, 一个梦想做发明家的程序员

    Java直接内存与非直接内存性能测试

    什么是直接内存与非直接内存 根据官方文档的描述: A byte buffer is either direct or non-direct. (也就是非堆内存);另一种是非直接内存(也就是堆内存)。 对于直接内存来说,JVM将会在IO操作上具有更高的性能,因为它直接作用于本地系统的IO操作。而非直接内存,也就是堆内存中的数据,如果要作IO操作,会先复制到直接内存,再利用本地IO处理。 从数据流的角度,非直接内存是下面这样的作用链: 本地IO-->直接内存-->非直接内存-->直接内存-->本地IO 而直接内存是: 本地IO-->直接内存-->本地IO 很明显,再做IO处理时,比如网络发送大量数据时 在数据量提升时,直接内存相比于非直接内存的申请 有十分十分十分明显的性能问题!

    1.8K50发布于 2018-01-17
  • 来自专栏码字搬砖

    JVM内存模型之直接内存

    直接内存 又称堆外内存,也就是说这不是jvm运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域,但这部分也会被频繁的使用,而且也可能导致OOM。 堆外内存有什么优点呢? 1 减少了垃圾回收的工作,因为垃圾回收会暂停其他的工作 2 可以提高性能,避免java堆和native堆(直接内存)来回复制数据。 使用场景 1.在JDK1.4之后加入了NIO,引入了一种基于通道与缓冲区的I/O方式,它可以使用Native库函数直接分配堆外内存,然后通过DirectByteBuffer对象作为这块内存的引用来进行操作 2.使用jdk内部未对外公开的unsafe来直接使用堆外内存,但不会被JVM回收 例子 /** * Created by shengjk1 on 2017/8/8 * 会自动回收的 */ //-verbose main(String[] args) { while (true){ ByteBuffer buffer=ByteBuffer.allocateDirect(10

    85330发布于 2018-10-24
  • 来自专栏springboot

    JVM之直接内存

    1、直接内存概述 不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域。 直接内存是在Java堆外的、直接向系统申请的内存区间。 来源于NIO,通过存在堆中的DirectByteBuffer操作Native内存 通常,访问直接内存的速度会优于Java堆。 ,省去了中间商赚差价 3、直接内存与 OOM 直接内存也可能导致OutofMemoryError异常 由于直接内存在Java堆外,因此它的大小不会直接受限于-Xmx指定的最大堆大小,但是系统内存是有限的 ,Java堆和直接内存的总和依然受限于操作系统能给出的最大内存直接内存的缺点为:   1)分配回收成本较高   2)不受JVM内存回收管理 直接内存大小可以通过MaxDirectMemorySize设置 如果不指定,默认与堆的最大值-Xmx参数值一致

    36100编辑于 2025-01-20
  • 来自专栏朱永胜的私房菜

    JVM-直接内存

    什么是 JVM 直接内存? JVM 直接内存(Direct Memory)是 JVM 运行时使用的一种特殊内存区域,它是 JVM 堆外的一块内存空间。 避免堆内存限制:JVM 直接内存不受 Java 堆大小的限制,可以充分利用系统的物理内存直接 I/O 操作:直接内存的零拷贝特性,可以直接进行 I/O 操作,提高了数据操作效率。 JVM 直接内存的缺点 手动释放内存:JVM 直接内存需要手动释放,如果忘记释放,会导致内存泄漏。 谨慎分配大量直接内存:由于直接内存的分配不受 Java 堆大小的限制,分配过多的直接内存可能导致系统资源的耗尽。 8. 它具有高性能、避免堆内存限制和直接 I/O 操作的优点,但需要手动管理内存释放,且内存管理较为复杂。在使用直接内存时,需要注意内存的释放和避免分配过多的直接内存。 本文由 mdnice 多平台发布

    1K30编辑于 2023-11-11
  • 来自专栏码农二狗

    golang直接操作共享内存

    前一段时间使用公司内部某个依赖共享内存的组件,其go版本api通过cgo提供。抛开我是个pure go狂热分子以外,采用cgo的方式实现会存在很多问题。 所以分析其源码后通过go进行重写,故在此分享一下直接通过golang去操作共享内存。 通过golang操作共享内存主要依赖了以下几个系统调用: SYS_SHMGET SYS_SHMCTL SYS_SHMAT SYS_SHMDT 操作步骤: 1.根据shm key获取/创建共享内存: shmid = 0 { return nil, errors.New(err.Error()) } 2.获取共享内存状态: //from bits/ipc.h type shmid_ds struct { 完成该步骤后,操作的对象实际就是共享内存对象,需要自行控制data race。

    4.4K30发布于 2020-01-03
  • 来自专栏大数据学习与分享

    JVM内存管理、直接内存和垃圾回收

    笔者将按下图分多篇文章详细阐述JVM: 1.jpg 本篇文章主要叙述JVM内存管理、直接内存、垃圾回收和常见的垃圾回收算法: 运行时数据区域 JVM在执行一些基于JVM运行的程序,典型的如Java 然而,当它调用的是本地方法时,虚拟机会保持Java栈不变,不会在线程的Java栈中压入新的栈帧,而是动态连接并直接调用指定的本地方法。 4. 但是当创建新创建的对象非常大,该对象会直接进入老年代。 3.png 5. 直接内存 直接内存(direct memory)不属于JVM运行时数据区的一部分,属于堆外内存,会被频繁使用,因此在设置各个内存范围时要留出一部分物理内存,否则也容易抛出OutOfMemoryError 标记整理算法 先标记(标记过程与标记清除算法一样),让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。这样可以解决内存碎片问题。 4.

    1.9K00发布于 2020-07-15
  • 来自专栏编码前线

    JAVA面试50讲之10直接(堆外)内存原理及使用

    DirectByteBuffer是堆外ByteBuffer,直接使用堆外内存空间存储数据,是NIO高性能的核心设计之一。本文来分析一下DirectByteBuffer的实现。 ,默认不对其 -XX:MaxDirectMemorySize=<size>,可以申请的最大DirectByteBuffer大小,默认与-Xmx相等 二、堆外内存详细使用 下面主要讲解如何使用直接内存(堆外内存 读写数据 在直接内存中,通过allocateDirect(int byte_length)申请直接内存。这段内存可以理解为一段普通的基于Byte的数组,因此插入和读取都跟普通的数组差不多。 cap=10]写string后 java.nio.DirectByteBuffer[pos=5 lim=10 cap=10] 读的时候,可以通过一个外部的byte[]数组进行读取。 由于没有找到直接操作直接内存的方法: 因此如果想在JVM应用中使用直接内存,需要申请一段堆中的空间,存放数据。

    3.3K51发布于 2019-01-23
  • 来自专栏分布式|微服务|性能优化|并发编程|源码分析

    JVM 彻底搞懂JVM内存区域及直接内存

    B站搜索“乐哥聊编程“有本篇文章配套视频‍ https://www.bilibili.com/video/BV1rg411v7rw 面试题:直接内存会导致OOM么? 本地方法栈 本地方法栈和虚拟机方法栈作用类似,不过它是为执行native方法服务 堆 堆是被线程共享的一个内存区域,大部分对象都在堆上分配,少部分允许在栈上分配(通过逃逸分析)。 方法区 方法区也是一块内存区域,它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。也包括运行时常量池。 jdk8以前主要通过永久代实现方法区 jdk8开始 通过元空间实现方法区 通过本地内存实现 直接内存 直接内存和堆内内存相对应,堆外内存就是把内存对象分配在Java虚拟机的堆以外的内存,这些内存直接受操作系统管理 传统BIO 访问 直接内存访问

    1.1K20编辑于 2022-12-22
  • 来自专栏渔夫

    Java-直接内存 DirectMemory 详解

    Java 直接内存 1. 设计逻辑  下面是 《深入理解 Java 虚拟机 第三版》2.2.7 小节 关于 Java 直接内存的描述。   直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域。 堆和 Native 堆(native heap)中来回复制数据,所以在一些场景中显著提高了性能; 直接内存出现 OutOfMemoryError 异常的原因是物理机器的内存是受限的,但是我们通常会忘记需要为直接内存在物理机中预留相关内存空间 垃圾回收  先的回答是不是的问题:直接内存也是会被 JVM 虚拟机管理进行完全不被引用的对象回收处理。  但是直接内存中的对象并不是如普通对象样被 GC 管理,这方面细节会在下一小节中提到。 3. 由于 heap 受到 GC 的直接管理,在 IO 写入的过程中 GC 可能会进行内存空间整理,这导致了一次 IO 写入的内存地址不完整。

    16.5K21发布于 2020-02-19
  • 来自专栏技术趋势

    JVM-直接内存(Direct Memory)

    直接内存(Direct Memory) 直接内存是Java堆之外的,直接向系统申请的内存空间,所以直接内存不是虚拟机的一部分,也不是《Java虚拟机规范》中定义的内存区域,也有可能导致OOM。 直接缓存区 直接内存也称直接缓存区,主要是解决一个java读取慢的问题,jdk1.4以后jvm 引入了NIO在操作系统划出了一块直接的缓存区可以直接被java访问。就是所称的零拷贝。 代码实现 非直接缓冲区 /** * @author: csh * @Date: 2021/5/8 18:49 * @Description:非直接缓存冲(堆内存) */ public class 模拟直接内存溢出 /** * @author: csh * @Date: 2021/5/13 18:37 * @Description:OOM 模拟直接内存溢出 * * Exception in ,都有利有弊,比如直接内存可以尽大限度的拓展内存空间,但是一但发生oom那排查起来非常麻烦,因为这块控制是非常难的,并且只有当full gc才会被回收,当然也是可以通过:通过-XX:MaxDirectMemorySize

    1.9K20发布于 2021-07-05
  • 来自专栏技术趋势

    直接内存满了导致的OOM

    /** * @author: csh * @Date: 2021/5/13 18:37 * @Description:OOM 模拟直接内存溢出 * * Exception in thread java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311) at com.memory.BufferTest2.main(BufferTest2.java:20) 通过查看内存发现 ,系统的内存呈现递增趋势,然后OOM后快速回落。 -Xmx20M -XX:MaxDirectMemorySize=10M ? 最后 OOM导致的溢出比较容易复现,并且很容易排查,在日常开发过程中要注意,不用的变量或引用要及时回收。

    1.8K40发布于 2021-07-29
  • 来自专栏Netty历险记

    Java通过JNI申请直接内存

    函数申请内存, 主要就是要观察在Java中, 堆外内存/直接内存的申请方式, 以及如何被管理的. 0x10, 为什么我们没有拿到区间开始的地址呢? 我们再改变一下, 不使用malloc分配内存, 而是使用mmap分配内存. 两个区间都是32MB, 与我们申请的吻合 哎,在这里我们看到使用mmap申请的内存, 我们拿到的起始地址就是maps中显示的地址, 是吻合的. 而Java方式拿到的地址, 还是一样, 偏差了0x10 简单说, malloc底层调用mmap系统函数申请内存(还有一种是brk系统函数), 只是malloc又对从操作系统拿到的内存做了手脚, 之所以做手脚是为了合理管理内存

    1.5K30编辑于 2022-06-02
  • 来自专栏IT杂记

    关于JVM直接内存触发Full GC

    今天在研究JVM的直接内存溢出时发现直接内存和堆内存一样,在直接内存快满时会触发full gc,full gc会将未被引用的对象及其指向的直接内存释放掉,如下为测试代码: package test.oom             ByteBuffer buf = ByteBuffer.allocateDirect(_1MB);                          // 将引用加入集合中防止被GC回收导致直接内存被释放  eden space 16384K, 6% used [0x00000000eb280000,0x00000000eb375d18,0x00000000ec280000) 当程序在执行第一次的时候内存为 300多M,当buf不添加到list集合中时,不会出现OOM,JVM每次都释放直接内存; 当buf添加到list中,则出现OOM,由于buf被引用,无法被full gc回收,导致直接内存为600M,而最大直接内存

    2.8K70发布于 2018-02-08
  • 来自专栏设计模式

    DMA(Direct Memory Access):直接内存访问

    DMA(Direct Memory Access):直接内存访问 一、传统CPU存取数据 CPU不直接存取外设的原因主要有两点: 速度差异:CPU的处理速度远高于外设,无法直接同步。 传统CPU获取数据的步骤如下: 加载外设数据到内存:外设数据首先被加载到内存中,因为内存的速度最接近CPU。 检查Cache:CPU检查Cache是否有需要的数据。 如果命中,直接返回数据。 二、认识DMA 1、什么是DMA DMA(Direct Memory Access)即直接存储器访问,通过内部控制器实现内存和外设之间的数据传输。 2、DMA的工作模式、数据传输方式、寻址模式 工作模式: 直接模式:DMA直接从源地址到目的地址传输数据。 FIFO模式:数据累计存储在FIFO缓冲器中,达到阈值后一次性发送。 四、合理的内存管理和访问控制 内存保护:通过设置内存访问权限,限制DMA访问。 内存分配和释放:合理管理内存,避免数据不一致和内存泄漏。

    3.6K20编辑于 2025-01-16
  • 来自专栏linux驱动个人学习

    直接内存回收中的等待队列

    直接内存回收过程中,有可能会造成当前需要分配内存的进程被加入一个等待队列,当整个node的空闲页数量满足要求时,由kswapd唤醒它重新获取内存。 如果当前进程加入到了pgdat->pfmemalloc_wait这个等待队列中,那么进程就不会进行直接内存回收,而是由kswapd唤醒后直接进行内存分配。 直接内存回收执行路径是: __alloc_pages_slowpath() -> __alloc_pages_direct_reclaim() -> __perform_reclaim() -> try_to_free_pages 之后进程由于内存不足,对zonelist进行直接回收时,会调用到try_to_free_pages(),在这个函数内,决定了进程是否加入到node结点的pgdat->pfmemalloc_wait这个等待队列中 如果不平衡,则加入到pgdat->pfmemalloc_wait等待队列中,如果平衡,则直接返回,并由当前进程自己进行直接内存回收。

    1.9K40发布于 2020-04-13
  • 来自专栏xingoo, 一个梦想做发明家的程序员

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

    本篇主要讲解如何使用直接内存(堆外内存),并按照下面的步骤进行说明: 相关背景-->读写操作-->关键属性-->读写实践-->扩展-->参考说明 希望对想使用直接内存的朋友,提供点快捷的参考。 读写数据 在直接内存中,通过allocateDirect(int byte_length)申请直接内存。这段内存可以理解为一段普通的基于Byte的数组,因此插入和读取都跟普通的数组差不多。 限制大小——limit 我们可能想要改变这段直接内存的大小,因此可以通过一个叫做Limit的属性设置。 limit则可以通过limit()获得,通过limit(int)进行设置。 public final int remaining() { return limit - position; } 读写实践 写操作主要就是按照自己的数据类型,写入到直接内存中 由于没有找到直接操作直接内存的方法: 因此如果想在JVM应用中使用直接内存,需要申请一段堆中的空间,存放数据。 如果有更好的方法,还请留言。

    1.6K91发布于 2018-01-17
  • 来自专栏一只程序原

    JVM内存与垃圾回收篇第11章直接内存

    第 11 章 直接内存 1、直接内存概述 直接内存 不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域。 直接内存是在Java堆外的、直接向系统申请的内存区间。 来源于NIO,通过存在堆中的DirectByteBuffer操作Native内存 通常,访问直接内存的速度会优于Java堆。即读写性能高。 因此出于性能考虑,读写频繁的场合可能会考虑使用直接内存。 OOM 直接内存也可能导致OutofMemoryError异常 由于直接内存在Java堆外,因此它的大小不会直接受限于-Xmx指定的最大堆大小,但是系统内存是有限的,Java堆和直接内存的总和依然受限于操作系统能给出的最大内存 直接内存的缺点为: 分配回收成本较高 不受JVM内存回收管理 直接内存大小可以通过MaxDirectMemorySize设置 如果不指定,默认与堆的最大值-Xmx参数值一致 ---- 代码示例 1 代码 Unsafe 类申请本地内存 /** * -Xmx20m -XX:MaxDirectMemorySize=10m * @author shkstart shkstart@126.com * @

    74720编辑于 2022-08-17
  • 来自专栏Reck Zhang

    Java 10 - 内存模型

    内存模型 主存储器与工作存储器 主存储器 方法区(Method Area) 方法区用于存储类的信息, 常量, 静态变量, 即时编译器编译后的代码. 当方法区无法满足内存分配需求时, 将抛出OutOfMeoryError. 堆(Heap) 堆在虚拟器启动时创建, 是JVM所管理的内存中最大的一块, 主要用于存放对象实例, 几乎所有的对象实例都在这里进行分配. 这也是GC的主要区域, 因此也教做GC堆, 如果堆中没有内存完成实例分配, 堆也无法进行扩展时, 将会抛出OutOfMemoryErrir异常. 字段引用 线程无法对主存储器直接进行操作, 因此也无法直接引用字段的值, 当线程希望引用字段的值时, 会将值从主存储器拷贝到工作存储器上. 通过此次拷贝的值, 会成为工作拷贝.

    37720发布于 2021-08-11
  • 来自专栏技术客栈

    Java直接内存分配和释放的讲解

    前言 直接内存是分配在JVM堆外的,那JVM是怎么对它进行管理的呢?本文主要介绍一下在Java中,直接内存的空间分配和释放的机制。 直接内存和堆内存的比较 在比较两者的性能时,我们分两方面来说。 申请空间的耗时:堆内存比较快 读写的耗时:直接内存比较快 直接内存申请空间其实是比较消耗性能的,所以并不适合频繁申请。 但直接内存在IO读写上的性能要优于堆内存,所以直接内存特别适合申请以后进行多次读写。 为什么在申请空间时,堆内存会更快? 堆内存的申请是直接从已分配的堆空间中取一块出来使用,不经过内存申请系统调用,而直接内存的申请则需要本地方法通过系统调用完成。 而为什么在IO读写时,直接内存比较快?因为直接内存使用的是零拷贝技术。 所以直接内存一般有两个使用场景: 复制很大的文件 频繁的IO操作,例如网络并发场景 直接内存由于是直接分配在堆外的,所以不受JVM堆的大小限制。

    1.5K40编辑于 2023-07-20
  • 来自专栏Lixj's Blog

    实战:OutOfMemoryError 异常(四) -- 本机直接内存溢出

    关于本机直接内存溢出的情况。 因为,虽然使用 DirectByteBuffer 分配内存也会抛出内存溢出异常,但它抛出异常时并没有真正向操作系统申请分配内存,而是通过计算得知内存无法分配,于是手动抛出异常,真正申请分配内存的方法是 代码如下: 使用unsafe分配本机内存 /** * -Xmx20M -XX:MaxDirectMemorySize=10M */ public class DirectMemoryOOM { ,一个明显的特征是在 Heap Dump 文件中不会看见明显的异常,如果在排查问题时发现 OOM 之后 Dump 文件很小,而程序中又直接或间接使用了NIO,那就可以考虑检查一下是不是这方面的原因。 高级特性与最佳实践》 Copyright: 采用 知识共享署名4.0 国际许可协议进行许可 Links: https://lixj.fun/archives/实战outofmemoryerror异常四--本机直接内存溢出

    57210编辑于 2022-06-10
领券