Netty 直接内存溢出问题
- 日志分析
Netty 内存溢出,但无详细到具体溢出位置

- 添加显示级别,定位到具体报错位置

- 监控直接内存使用情况,可以使用如下代码,在启动时加载(通过反射获取到直接内存使用情况)
package netty.util;
import java.lang.reflect.Field;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ReflectionUtils;
import io.netty.util.internal.PlatformDependent;
/*直接内存监控*/
public class DirectMemoryReporter {
private static final Logger LOGGER = LoggerFactory.getLogger(DirectMemoryReporter.class);
private static final int _1K = 1024;
private static final String BUSINESS_KEY = "netty_direct_memory";
private AtomicLong directMemory;
public void init() {
Field field = ReflectionUtils.findField(PlatformDependent.class, "DIRECT_MEMORY_COUNTER");
field.setAccessible(true);
try {
directMemory = ((AtomicLong) field.get(PlatformDependent.class));
startReport();
} catch (IllegalAccessException e) {
LOGGER.error("netty_direct_memory error", e);
}
}
public void startReport() {
Runnable runnable = () -> {
doReport();
};
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
service.scheduleAtFixedRate(runnable, 30, 1, TimeUnit.SECONDS);
}
private void doReport() {
try {
int memoryInKB = (int) (directMemory.get());
LOGGER.info("{}:{}KB", BUSINESS_KEY, memoryInKB/1024);
} catch (Exception e) {
LOGGER.error("netty_direct_memory error", e);
}
}
}
- idea 配置直接内存大小 方便测试

- 最终定位问题代码如下:添加了release后解决问题
使用 ByteBuf.readBytes 读取一定的字节数ByteBuf对象,如果长时间接收数据,就会导致内存溢出
// 读取包头 4个字节(此方法会产生新的ByteBuf,需要手动释放堆外内存;或者使用readBytes(byte[])) ByteBuf da = in.readBytes(4); da.release();
查看源码,注意标红区域,有说明会创建一个新的buffer

本文来自博客园,作者:isme_533,转载请注明原文链接:https://www.cnblogs.com/isme533/p/16875057.html
浙公网安备 33010602011771号