-XX:MaxDirectMemorySize:通过JVM参数是可以设置你最大可以使用的堆外内存的大小的,比如说设置堆外内存最大可以使用1GB,此时已经使用了950MB空间了,然后呢,你此时要申请一块80MB的堆外内存
会发现说,堆外内存已经不够了,此时不能直接分配堆外内存了
DirectByteBuffer,这个对象是JVM堆内存里的一个对象,但是这个DirectByteBuffer里面包含指针,引用了一块堆外的内存
1、如果堆外内存足够,就直接预留一部分内存
2、如果堆外内存不足,则将已经被 JVM 垃圾回收的 DirectBuffer 对象的堆外内存释放
3、如果进行一次堆外内存资源回收后,还不够进行本次堆外内存分配的话,则进行 System.gc()
4、如果 9 次尝试后依旧没有足够的可用堆外内存,则抛异常
5、实际分配内存
jvm专栏,或者是对jvm的垃圾回收有一定的理解的话
jvm一般分为young gc和full gc,无论是发生哪种gc,都可能会回收掉一些没有GC roots变量引用的DirectByteBuffer对象,回收掉了之后,就会主动释放他们引用的那些堆外内存,是这样子的
DirectByteBuffer回收,就会回收关联的堆外内存,或者是内部有一个cleaner对象,可以用反射获取他,然后调用他的clean方法来主动释放内存
如果依靠jvm gc机制,可能DirectByteBuffer躲过N次minor gc进入了老年代,然后老年代迟迟没有放满,因此迟迟没有回收,此时可能会导致DirectByteBuffer对象一直在引用堆外内存
这样当你要分配更多的堆外内存时,无法腾出来更多的内存,就会有堆外内存溢出了
堆内内存的OOM一样,out of memory,内存耗尽,实在是没有空闲的内存空间给你来使用了,因为所有的内存此时都别别人在使用,你要申请一块新的内存空间,实在是没有了,所以就OOM
堆外内存的溢出,也是一样的