netty 最大非堆内存大小限制

读码心得

近期碰到 nettyio.netty.util.internal.OutOfDirectMemoryError 错误,排查发现是 netty 最大非堆内存大小限制导致的。

netty 4.1.70.Final 版本,io.netty.util.internal.PlatformDependent 类中,MAX_DIRECT_MEMORY 常量定义如下:

通过 maxDirectMemory0() 方法,获取系统最大非堆内存大小,单位为字节。

  1. 其通过多种方式获取最大非堆内存大小,优先级如下:

    1. 通过反射执行 VM.maxDirectMemory() 方法获取
    2. 通过 MXBean 解析 JVM 参数(-XX:MaxDirectMemorySize)获取
  2. 若上述读出的值都是 0,则使用 Runtime.getRuntime().maxMemory() 读取当前最大可使用内存作为最大非堆内存大小

代码见: PlatformDependent#maxDirectMemory0

真正使用时,使用另一个参数,DIRECT_MEMORY_LIMIT,作为最大非堆内存大小,单位为字节,其获取代码如下:

long maxDirectMemory = SystemPropertyUtil.getLong("io.netty.maxDirectMemory", -1);
...
logger.debug("-Dio.netty.maxDirectMemory: {} bytes", maxDirectMemory);
DIRECT_MEMORY_LIMIT = maxDirectMemory >= 1 ? maxDirectMemory : MAX_DIRECT_MEMORY;

所以,若未设置 -XX:MaxDirectMemorySize 参数,且设置了最大堆大小较小,那么 netty 最大非堆内存大小就会受限于最大堆大小。这容易导致 nettyio.netty.util.internal.OutOfDirectMemoryError 错误。