Java直接内存

简介: Java直接内存, ByteBuffer,DirectByteBuffer,PhantomReference,ReferenceHandler
  • 直接内存申请空间其实是比较消耗性能,需要本地方法通过系统调用完成
  • 直接内存在IO读写上的性能要优于堆内存,所以直接内存特别适合申请以后进行多次读写
  • 堆外内存优势在 IO 操作上,对于网络 IO,使用 Socket 发送数据时,能够节省堆内存到堆外内存的数据拷贝
  • 零拷贝

    • 复制很大的文件
    • 频繁的IO操作,例如网络并发场景
  • 不受JVM堆的大小限制
  • 会受到本机总内存(包括RAM及SWAP区或者分页文件)的大小及处理器寻址空间的限制,可能会抛出OutOfMemoryError异常
  • 直接内存的最大大小可以通过-XX:MaxDirectMemorySize来设置,默认是64M
  • ByteBuffer.allocateDirect()
  • 由于申请内存前可能会调用 System.gc(),所以谨慎设置 -XX:+DisableExplicitGC 这个选项,这个参数作用是禁止代码中显示触发的 Full GC
  • 回收

    • 自动回收
    • GC 时会扫描 DirectByteBuffer 对象是否有有效引用指向该对象,如没有,在回收 DirectByteBuffer 对象的同时且会回收其占用的堆外内存
    • 虚引用(Phantom Reference)

      • 也称为幽灵引用或者幻影引用
      • 一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。
      • 为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知
      • GC过程中如果发现某个对象除了只有PhantomReference引用它之外,并没有其他的地方引用它了,那将会把这个引用放到java.lang.ref.Reference.pending队列里,ReferenceHandler这个守护线程会处理pending队列里,执行一些后置处理,这里是调用Cleaner的clean方法
      • 而DirectByteBuffer构造方法内创建了一个Cleaner对象, Cleaner继承了PhantomReference,其referent为DirectByteBuffer,也是通过Cleaner调用unsafe.freeMemory(address)来释放直接内存
    • 手动回收

      • DirectByteBuffer 实现了 DirectBuffer 接口,这个接口有 cleaner 方法可以获取 cleaner 对象。
      public static void clean(final ByteBuffer byteBuffer) {  
        if (byteBuffer.isDirect()) {  
            ((DirectBuffer)byteBuffer).cleaner().clean();  
        }  
      }
      • Netty 中的堆外内存池就是使用反射来实现手动回收方式进行回收的。
      • 当堆空间非常富余,直接内存占用虽然很高,但并不会自发引起 GC——哪怕直接内存已经用满。 如果不触发 GC,直接内存可能就会溢出。因此,只能人为去触发 GC,从而回收直接内存。
  • DirectByteBuffer 这个类是 JDK 提供使用堆外内存的一种途径,当然常见的业务开发一般不会接触到,即使涉及到也可能是框架(如 Netty、RPC 等)使用的,对框架使用者来说也是透明的
目录
相关文章
|
14天前
|
存储 Java 编译器
Java内存区域详解
Java内存区域详解
29 0
Java内存区域详解
|
24天前
|
缓存 算法 Java
Java内存管理与调优:释放应用潜能的关键
【4月更文挑战第2天】Java内存管理关乎性能与稳定性。理解JVM内存结构,如堆和栈,是优化基础。内存泄漏是常见问题,需谨慎管理对象生命周期,并使用工具如VisualVM检测。有效字符串处理、选择合适数据结构和算法能提升效率。垃圾回收自动回收内存,但策略调整影响性能,如选择不同类型的垃圾回收器。其他优化包括调整堆大小、使用对象池和缓存。掌握这些技巧,开发者能优化应用,提升系统性能。
|
1月前
|
监控 Java 数据库连接
解析与预防:Java中的内存泄漏问题
解析与预防:Java中的内存泄漏问题
|
21天前
|
缓存 安全 Java
Java并发编程进阶:深入理解Java内存模型
【4月更文挑战第6天】Java内存模型(JMM)是多线程编程的关键,定义了线程间共享变量读写的规则,确保数据一致性和可见性。主要包括原子性、可见性和有序性三大特性。Happens-Before原则规定操作顺序,内存屏障和锁则保障这些原则的实施。理解JMM和相关机制对于编写线程安全、高性能的Java并发程序至关重要。
|
28天前
|
缓存 Java C#
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍(一)
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍
79 0
|
2月前
|
存储 安全 Java
一文带你读懂深入理解Java内存模型
java内存模型(Java Memory Model,JMM)是java虚拟机规范定义的,用来屏蔽掉java程序在各种不同的硬件和操作系统对内存的访问的差异,这样就可以实现java程序在各种不同的平台上都能达到内存访问的一致性。可以避免像c++等直接使用物理硬件和操作系统的内存模型在不同操作系统和硬件平台下表现不同,比如有些c/c++程序可能在windows平台运行正常,而在linux平台却运行有问题。 物理硬件和内存
21 1
|
2天前
|
Java 程序员 数据库连接
Java从入门到精通:3.3.2性能优化与调优——内存管理篇
Java从入门到精通:3.3.2性能优化与调优——内存管理篇
Java从入门到精通:3.3.2性能优化与调优——内存管理篇
|
3天前
|
存储 安全 Java
滚雪球学Java(19):JavaSE中的内存管理:你所不知道的秘密
【4月更文挑战第8天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
30 4
滚雪球学Java(19):JavaSE中的内存管理:你所不知道的秘密
|
11天前
|
存储 缓存 监控
Java内存管理:垃圾回收与内存泄漏
【4月更文挑战第16天】本文探讨了Java的内存管理机制,重点在于垃圾回收和内存泄漏。垃圾回收通过标记-清除过程回收无用对象,Java提供了多种GC类型,如Serial、Parallel、CMS和G1。内存泄漏导致内存无法释放,常见原因包括静态集合、监听器、内部类、未关闭资源和缓存。内存泄漏影响性能,可能导致应用崩溃。避免内存泄漏的策略包括代码审查、使用分析工具、合理设计和及时释放资源。理解这些原理对开发高性能Java应用至关重要。
|
19天前
|
存储 缓存 安全
【企业级理解】高效并发之Java内存模型
【企业级理解】高效并发之Java内存模型