误用线程池ThreadPoolExecutor导致堆外内存增加宕机

最近遇到一个问题原本虚拟机分配了2G的堆大小,发现OS用top命令看,进程的VIRT内存一直增加,而且RES也一直往上增加,最后前者达到了16G,后者达到了8G,最后内存整个进程宕调
后来尝试重现问题,打了JAVA线程堆栈,发现堆栈里面大量的pool的线程,多达上万个。

就是有个人写代码,误用JAVA线程池,每次用都新new一个线程池ThreadPoolExecutor,
最后自己写代码测试,确实每次new会占用堆外堆存,没有跟踪到底层,但是线程池是管理线程的,虚拟机线程肯定是要跟OS申请线程资源的,linux中线程作为轻量进程,每fork一个肯定会占用OS的资源,相对于java虚拟机堆内内存来说,即是占用了堆外内存;而虚拟机本身由于线程池不释放,老生代会一直缓慢增加,但是没有堆外内存那么厉害,当老生代一直增加到100%后,虚拟机本身会报内存溢出。而操作系统层面,由于大量VIRT被占用,就连简单的top有时也会因为没有办法分配内存而执行不了。

猜你喜欢

转载自gooneal.iteye.com/blog/2160030