nio 引发的 memory leak
上周, 某同事报bug, 说疑似使用了公司的 rpc 框架后发生了 堆外oom 异常导致程序挂了。
仔细一想, 好像当初的老版本框架好像没有用到堆外内存呀。
然后, 了解过详情后测试发现, 当把 业务线程池调小后, 发现从运行到挂的时间 可以更久些。
也就是所发生了泄漏。
根据错误堆栈以及 google 上的搜索, 找到前twitter 开发人写的blog 发现是如果你进行网络编程并且使用 nio 时,当调用系统 api 时 (write), 会在堆外 malloc 一块空间,将java 内存的数据写入后 进行 systemcall。
然后,这块空间不会释放,而是缓存着,留给这个线程的下一次请求使用(ps, 这个大小时无限制的)。
所以, 当线程老多老多时,然后线程池的 coreSize
也非常大时, 那么就会泄漏。
那么这么严重的问题,为啥java 官方 不早早的修复呢?
分析了下。
- 首先,既然用了nio, 就不应当一个线程一个 nio 连接, 这个存在本身就很不合理。
- 老框架确实存在些问题, new 出来的线程池的 coreSize 和 MaxSize 是一样的,所以在线程上, 不会自动销毁, 间接使内存泄漏跟容易出现。
综上,出现了以上问题, 所以 java 官方也不急着修。
临时解决方案就是将 线程池调小些。
进阶解决方案是, 不要每个业务线程以 helloworld 的方式使用第三方依赖。 像这种内部nio的,应该封装出一个连接池什么的。