nio 引发的 memory leak

上周, 某同事报bug, 说疑似使用了公司的 rpc 框架后发生了 堆外oom 异常导致程序挂了。

仔细一想, 好像当初的老版本框架好像没有用到堆外内存呀。

然后, 了解过详情后测试发现, 当把 业务线程池调小后, 发现从运行到挂的时间 可以更久些。

也就是所发生了泄漏。

根据错误堆栈以及 google 上的搜索, 找到前twitter 开发人写的blog 发现是如果你进行网络编程并且使用 nio 时,当调用系统 api 时 (write), 会在堆外 malloc 一块空间,将java 内存的数据写入后 进行 systemcall。

然后,这块空间不会释放,而是缓存着,留给这个线程的下一次请求使用(ps, 这个大小时无限制的)。

所以, 当线程老多老多时,然后线程池的 coreSize 也非常大时, 那么就会泄漏。

那么这么严重的问题,为啥java 官方 不早早的修复呢?

分析了下。

  1. 首先,既然用了nio, 就不应当一个线程一个 nio 连接, 这个存在本身就很不合理。
  2. 老框架确实存在些问题, new 出来的线程池的 coreSize 和 MaxSize 是一样的,所以在线程上, 不会自动销毁, 间接使内存泄漏跟容易出现。

综上,出现了以上问题, 所以 java 官方也不急着修。

临时解决方案就是将 线程池调小些。

进阶解决方案是, 不要每个业务线程以 helloworld 的方式使用第三方依赖。 像这种内部nio的,应该封装出一个连接池什么的。

avatar

lelouchcr's blog