简单的java内存问题定位
最近碰到oom的问题。一个Java进程我heap就分配了768M,整体内存大小限制了2GB,可每次都是运行没几个小时就超过内存限制被mesos给kill掉重启。
有人肯定会说这个肯定是堆外内存搞的。
看看这里堆外总共用了100M左右。
那还有direct memory这些。我的Java启动参数是如下的:
1 | -Xms768m -Xmx768m -Xss256k -XX:MaxDirectMemorySize=250m -XX:CompressedClassSpaceSize=256M |
这些都限制了,可还是会没多久会重启。
内存肯定是超了,那到底内存是哪些东西呢? 那我们就用gdb来dump出来慢慢看了。
1 |
|
然后我们执行一下就会把该进程的所有内存空间的内容给dump出来。
1 | ./gdb-dump.sh 10130 |
最后就得到所有内存空间的内容。 看了下,下面几个MB空间大小的问题就比较可疑了。
然后就直接strings命令看了下文件内容,果然是很多垃圾,有几个小时之前的日志,也有几个小时之前处理的文件流。
虽然这里的大小不是64M,但是内存地址空间就是64M的大小。那就放狗查了下,这个是Java和glibc配合的问题。
最简单的方式就启动前加上对应的环境变量
1 | export MALLOC_ARENA_MAX=8 |
但是Java里也可以自己去控制,而不是glibc来管理,不过这样是不是就跟写C没什么区别了,什么都要自己去处理。
还有一种就弃用glibc,而用tcmalloc来替换,但是结果未可知,这个需要测试下。同时对于是否影响别的进程也是需要测试。
不过以我司现有的人力,估计也不会去搞了。