直接内存的原理 直接内存分配和释放 禁用显式垃圾回收

直接内存

如何应用直接内存进行IO操作

使用传统方式和分配直接内存的方式进行IO操作
传统IO使用了大概3s,而byteBuffer只用了不到1s
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

直接内存的原理

传统文件读写的原理如下
文件读写开始,CPU 的状态就从 用户态转换到内核态,内存中也会划出一块区域作为系统缓冲区,用来缓存文件数据。Java想要读写文件,就要把系统缓冲区内的内容再读到Java缓冲区,然后再进行读写。
在这里插入图片描述
直接内存的原理

而当Java调用了ByteBuffer.allocateDiret() 方法时,会直接分配操作系统的内存。和原本的系统内存缓冲区不同的是,这块内存Java可以直接操作,是操作系统代码和Java代码共享的一块区域。
这样需要读写文件的时候,系统代码会将磁盘文件读取到直接内存,而Java程序也可以从直接内存中直接读取文件,少了一步复制的步骤。因此,读写文件的速度就得到了成倍的提升。
在这里插入图片描述

直接内存的内存溢出

直接内存虽然不处于JVM内部,但仍处于 内存内部,也会有内存溢出的危险。

程序中,循环分配直接内存的空间100M,然后使用list进行引用,使其不会成为垃圾
在这里插入图片描述

在这里插入图片描述
循环了36次之后内存溢出

直接内存如何进行分配和释放

现在看一个程序,来展示一下直接内存的分配和释放

程序中,直接使用ByteBuffer.allocateDirect() 函数分配了1GB内存,然后系统等待用户输入,这时我们检查内存占用,发现多了1GB
在这里插入图片描述

释放直接内存时,直接设置变量为null,让直接内存失去引用。过一会查看内存占用,发现之前的1GB占用不见了,说明1GB的资源被释放了。

但是直接内存是不受JVM的管理的,那么直接内存的分配和释放的原理是什么呢

直接内存分配和释放的原理

直接内存的分配和回收其实是通过一个叫Unsafe 的类对象完成的,这个类对象不推荐程序员平时使用。
unsafe
执行效果
在这里插入图片描述

在这里插入图片描述

那么ByteBuffer 和 Unsafe 是怎么联系到一起的呢?
直接查看ByteBuffer的构造器,发现直接调用了Unsafe对象。调用unsafe的allocateMemory() 方法分配内存,而最后使用了Cleaner对象释放了内存。
byteBuffer构造器
Clean 是如何进行释放内存的呢?

看函数,Cleaner创建了一个回调任务,在create方法中,关联了当前对象this(DirectByteBuffer对象),并定义了回调对象Deallocator。这个Deallocator是一个Runnable对象,被调用时会执行run()方法,而在这个方法中,我们可以看到unsafe对象的freeMemory方法。

而Cleaner又是什么呢,它是一个虚引用对象(实现了PhantomReferrence)。虚引用对象的特点是,当关联的对象被垃圾回收之后,自身就会调用clean() 方法。而在这个clean() 方法中,我们看到它调用了Deallocator 的run() 方法。后台有一个线程一直会检查虚引用对象,并使虚引用对象做这些事。

在这里插入图片描述

在这里插入图片描述

总的来说就是

  • 使用了 Unsafe 对象完成直接内存的分配回收,并且回收需要主动调用 freeMemory 方法
  • ByteBuffer 的实现类内部,使用了 Cleaner (虚引用)来监测 ByteBuffer 对象,一旦ByteBuffer 对象被垃圾回收,那么就会由 ReferenceHandler 线程通过 Cleaner 的 clean 方法调用 freeMemory 来释放直接内存

禁用显式垃圾回收

可以在启动Java程序的时候,加上参数-XX:+DisableExplicitGC 就可以禁用显式垃圾回收,也就是 禁用程序员直接使用System.gc() 来触发垃圾回收。
这样做的目的一般是为了检测程序在内存占用的性能。
比如:
在这里插入图片描述
这段代码中,只要Java对象不被垃圾回收,直接内存也不会进行释放。这样就会影响直接内存的性能。这种时候,我们就直接使用unsafe来freeMemory即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值