JVM 直接内存的分配与释放详解和底层实现 我不是女神ヾ 2022-12-16 09:24 569阅读 0赞 直接内存 定义: * 常见于 NIO 操作时,用于数据缓冲区 * 分配回收成本较高,但读写性能高 * 不受 JVM 内存回收管理 import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; public class memory_overflow { static int _100Mb = 1024 * 1024 * 100; public static void main(String[] args) { List<ByteBuffer> list = new ArrayList<>(); int i = 0; try { while (true) { ByteBuffer byteBuffer = ByteBuffer.allocateDirect(_100Mb); list.add(byteBuffer); i++; } } finally { System.out.println(i); } } } 直接内存分配,每次内存分配100m,一直分配空间,运行代码会抛出异常 java.lang.OutOfMemoryError: Direct buffer memory , 表示直接内存不足。 内存的占用 释放原理 在这里我们运行一段代码,给添加一个g的内存,之后再进行释放内存,在任务管理器当中进行查看内存的占用情况。使用以下代码段进行测试 import java.io.IOException; import java.nio.ByteBuffer; public class GC_memory { static int _1Gb = 1024 * 1024 * 1024; public static void main(String[] args) throws IOException { ByteBuffer byteBuffer = ByteBuffer.allocateDirect(_1Gb); System.out.println("分配完毕..."); System.in.read(); System.out.println("开始释放..."); byteBuffer = null; System.gc(); // 显式的垃圾回收,Full GC System.in.read(); } } 在按压第一次回车后分配内存,再一次按压回车后将内存释放掉。 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0OTczMTU5_size_16_color_FFFFFF_t_70_pic_center] 释放原理的底层实现 直接内存分配的底层原理:Unsafe ; 使用了 Unsafe 对象完成直接内存的分配回收,并且回收需要主动调用 freeMemory 方法 ByteBuffer 的实现类内部,使用了 Cleaner (虚引用)来监测 ByteBuffer 对象,一旦 ByteBuffer 对象被垃圾回收,那么就会由 ReferenceHandler 线程通过 Cleaner 的 clean 方法调用 freeMemory 来释放直接内存 使用以下代码段进行演示 package direct; import sun.misc.Unsafe; import java.io.IOException; import java.lang.reflect.Field; public class GC_memory_bottom { static int _1Gb = 1024 * 1024 * 1024; public static void main(String[] args) throws IOException { Unsafe unsafe = getUnsafe(); // 分配内存 long base = unsafe.allocateMemory(_1Gb); unsafe.setMemory(base, _1Gb, (byte) 0); System.in.read(); // 释放内存 unsafe.freeMemory(base); System.in.read(); } public static Unsafe getUnsafe() { try { Field f = Unsafe.class.getDeclaredField("theUnsafe"); f.setAccessible(true); Unsafe unsafe = (Unsafe) f.get(null); return unsafe; } catch (NoSuchFieldException | IllegalAccessException e) { throw new RuntimeException(e); } } } 执行代码,在任务管理器当中查看内存占用,再分配了1g的内存后,会上升,内存释放后,又会下降下来。 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0OTczMTU5_size_16_color_FFFFFF_t_70_pic_center 1] 性能调优 禁用显示的垃圾回收机制。使用参数 -XX:+DisableExplicitGC 禁用之后直接内存的回收会受到影响,在 内存的占用 释放原理 这里的代码段进行添加参数。进行测试: 在进行内存释放的时候通常要采用unsafe对象进行释放 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0OTczMTU5_size_16_color_FFFFFF_t_70_pic_center 2] [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0OTczMTU5_size_16_color_FFFFFF_t_70_pic_center]: /images/20221123/48ca2824025b47669ea7305658ab9a91.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0OTczMTU5_size_16_color_FFFFFF_t_70_pic_center 1]: /images/20221123/2713ab2c046a4db4971b573ed551d108.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0OTczMTU5_size_16_color_FFFFFF_t_70_pic_center 2]: /images/20221123/45ce9ab09bed4389b1a7f7e19bdc8958.png
相关 【JVM】详解直接内存 文章目录 1. 直接内存概述 2. 直接内存的使用 2.1 Java缓冲区 2.2 直接内存 3. 直接内存的释放 短命女/ 2024年03月27日 09:29/ 0 赞/ 77 阅读
相关 JVM篇: 直接内存 Direct Memory 不是虚拟机运行时数据区的一部分,也不是《Java 虚拟机规范》中定义的内存区域。 直接内存是在 Java 堆外的、直接向系统申请的内存区间。 素颜马尾好姑娘i/ 2024年03月17日 17:42/ 0 赞/ 72 阅读
相关 jvm 直接内存 -------------------- jvm 直接内存 直接内存使用的是系统内存,java nio使用native函数获得堆外内存; 使用DirectByt Dear 丶/ 2023年07月19日 08:13/ 0 赞/ 8 阅读
相关 JVM 直接内存的分配与释放详解和底层实现 直接内存 定义: 常见于 NIO 操作时,用于数据缓冲区 分配回收成本较高,但读写性能高 不受 JVM 内存回收管理 import java.n 我不是女神ヾ/ 2022年12月16日 09:24/ 0 赞/ 570 阅读
相关 JVM 直接内存 概述 直接内存并不是虚拟机运行时数据区的一部分,也不是Java 虚拟机规范中农定义的内存区域。在JDK1.4 中新加入了NIO(New Input/Output)类,引入了一 谁借莪1个温暖的怀抱¢/ 2022年06月02日 04:41/ 0 赞/ 282 阅读
相关 JVM方法区内存分配 方法区内存 \-XX:PermSize 设置初始化方法区内存 \-XX:MaxPermSize 设置最大方法区,也称永久区的内存 默认情况下,为64M 向右看齐/ 2022年05月16日 08:07/ 0 赞/ 371 阅读
相关 Java直接内存分配与释放原理 前言 在Java中分配直接内存大有如下三种主要方式: 1.Unsafe.allocateMemory() 2.ByteBuffer.allocateDirect() 快来打我*/ 2022年02月25日 14:53/ 0 赞/ 344 阅读
相关 结构体的使用和动态内存的分配及释放 结构体 什么是结构体?结构体是用户根据实际需要自己定义的复合数据类型。结构体的出现是为了表示一些复杂的数据,而普通的数据类型无法满足要求。 结构体的定义: str Dear 丶/ 2021年12月23日 11:25/ 0 赞/ 356 阅读
相关 05-数据结构_预备知识-动态内存的分配和释放 参看 C语言部分 1, 分配 malloc 2, 释放 free 3, 增删 realloc include <stdio.h> 向右看齐/ 2021年12月22日 08:23/ 0 赞/ 313 阅读
相关 jvm对象内存的分配策略 Java所承诺的自动内存管理主要是针对对象内存的回收和对象内存的分配。 在Java虚拟机的五块内存空间中,程序计数器、Java虚拟机栈、本地方法栈内存的分配和回收都具有确定性 灰太狼/ 2021年11月23日 08:08/ 0 赞/ 371 阅读