java 堆外内存常见误解

背景:

你有没有过错觉,以为java堆外内存都是受-XX:MaxDirectMemorySize大小控制的?这个先入为主的观点对我们查找堆外内存问题是非常不利的

java堆外内存的组成

1.元空间占用,这里是存放java类元数据的地方,其受到-XX:Maxmetaspacesize大小的限制,也就是如果设置了这个-XX:Maxmetaspacesize值,你可以肯定元空间的堆外内存占用不会超过配置值

2.使用ByteBuffer.allocateDirect分配直接内存,这部分内存是受-XX:MaxDirectMemorySize大小限制的,也就是通过这个方法申请的内存不会超出-XX:MaxDirectMemorySize的大小限制,一旦超出,就会发生OOM,此外这部分内存可以通过正常的Full gc去回收,因为java的堆内持有执行这部分堆外内存的引用,当回收堆内的地址引用时,会顺带着回收堆外的内存占用
java 堆外内存常见误解_第1张图片
3.直接使用Unsafe.allocateMemory(size)或者java 堆外内存常见误解_第2张图片
分配的堆外内存,这部分内存不由任何的JVM参数限制,唯一的释放这种内存的方式就是手动通过Unsafe.freeMemory(address)的方式进行释放,也就是这部分堆外内存完全由应用管理,JVM没有途径可以限制这部分堆外内存的使用。 PS: 例如netty 通过其自定义的参数-Dio.netty.maxDirectMemory限制netty自身申请的这部分堆外内存最大值

总结:

JVM参数-XX:MaxDirectMemorySize并不能控制元空间以及应用自身通过Unsafe.allocateMemory分片的堆外内存大小,这些内存的大小完全仅仅由物理机的最大内存大小限制,所以我们排查堆外内存问题时,不要以为通过-XX:MaxDirectMemorySize就可以完全控制堆外内存的最大大小,有些堆外内存的控制完全由应用占用的,例如Netty本身控制的

你可能感兴趣的:(netty,java性能,java,开发语言)