JVM-直接内存原理
本文最后更新于:2022年1月13日 下午
JVM直接内存
1. 直接内存原理
直接内存是操作系统内存的一部分,并不是由虚拟机管理的内存,不受垃圾回收管理器的管理。
正常情况下的内存使用:
根据上图所示,java缓冲区的内存是由JVM进行分配和回收的,JVM本身相对于操作系统来说属于用户态的应用程序,如果进行文件读写操作,需要由用户态转到内核态,由操作系统提供读写服务。因此在进行文件读写时,需要进过两次拷贝。
直接内存的使用情况:
根据上图可见,当java程序申请直接内存时,使用的的系统内存,并且java程序和操作系统都可以对这块内存进行操作,因此可以加快读写速度,但是直接内存不受GC的管理,分配的代价也比较大,常用于NIO操作,用作读写缓冲区。
当然,如果申请的直接内存过大,会出现OutOfMemoryError异常。
2. 直接内存的释放和回收
使用ByteBuffer来申请直接内存:
1 |
|
1 |
|
DirectByteBuffer的内部实现如下:
1 |
|
根据源码,我们可以看到申请内存实际上是通过一个UNSAFE对象来实现的,base = UNSAFE.allocateMemory(size);
,通过使用allocateMemory方法来申请直接内存。同样在释放直接内存时,需要我们主动调用UNSAFE的freeMemory方法来释放内存。
具体在DirectByteBuffer的实现方法中,我们看到了使用了一个Cleaner(虚引用)来检测this,就是我们当前的ByteBuffer对象,一旦ByteBuffer对象被垃圾回收,那么就会由ReferenceHandler线程通过Cleaner的clean方法来调用freeMemory方法来释放直接内存。
根据源码可以看到,在创建Cleaner的同时,传入了Deallocator对象,在Deallocator对象存在一个run方法,该run方法内部调用了UNSAFE的freeMemory方法来释放直接内存。
1 |
|
在实际使用中,当ByteBuffer对象被回收后,Cleaner便可以通过UNSAFE的freeMemory方法来回收直接内存,当然,我们也可以直接调用UNSAFE的freeMemory方法来回收直接内存,但是UNSAFE一般由JVM内部使用,上层程序无法直接使用,需要通过反射来间接获取UNSAFE对象。
本文作者: ziyikee
本文链接: https://ziyikee.fun/2022/01/08/JVM-%E7%9B%B4%E6%8E%A5%E5%86%85%E5%AD%98%E5%8E%9F%E7%90%86/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!