最近遇到一个问题原本虚拟机分配了2G的堆大小,发现OS用top命令看,进程的VIRT内存一直增加,而且RES也一直往上增加,最后前者达到了16G,后者达到了8G,最后内存整个进程宕调
后来尝试重现问题,打了JAVA线程堆栈,发现堆栈里面大量的pool的线程,多达上万个。
就是有个人写代码,误用JAVA线程池,每次用都新new一个线程池ThreadPoolExecutor,
最后自己写代码测试,确实每次new会占用堆外堆存,没有跟踪到底层,但是线程池是管理线程的,虚拟机线程肯定是要跟OS申请线程资源的,linux中线程作为轻量进程,每fork一个肯定会占用OS的资源,相对于java虚拟机堆内内存来说,即是占用了堆外内存;而虚拟机本身由于线程池不释放,老生代会一直缓慢增加,但是没有堆外内存那么厉害,当老生代一直增加到100%后,虚拟机本身会报内存溢出。而操作系统层面,由于大量VIRT被占用,就连简单的top有时也会因为没有办法分配内存而执行不了。
后来尝试重现问题,打了JAVA线程堆栈,发现堆栈里面大量的pool的线程,多达上万个。
就是有个人写代码,误用JAVA线程池,每次用都新new一个线程池ThreadPoolExecutor,
最后自己写代码测试,确实每次new会占用堆外堆存,没有跟踪到底层,但是线程池是管理线程的,虚拟机线程肯定是要跟OS申请线程资源的,linux中线程作为轻量进程,每fork一个肯定会占用OS的资源,相对于java虚拟机堆内内存来说,即是占用了堆外内存;而虚拟机本身由于线程池不释放,老生代会一直缓慢增加,但是没有堆外内存那么厉害,当老生代一直增加到100%后,虚拟机本身会报内存溢出。而操作系统层面,由于大量VIRT被占用,就连简单的top有时也会因为没有办法分配内存而执行不了。
本文讨论了在Java开发中误用线程池导致的虚拟机堆外内存占用和OS资源消耗问题。通过分析线程池使用不当引起的大量线程创建,解释了如何优化线程池配置以避免此类问题,并防止内存溢出和系统资源枯竭。
170万+

被折叠的 条评论
为什么被折叠?



