好久不收拾,这里都长草了。先广告一下,弄了一个shawnma.com的域名(其实去年就申请了,然后就给忘了,浪费了50元啊!),以后shawnma.xomud.com就不搞了,xomud.com我也不打算续了,有人想要么,可以转让,哈。
这是一个很久以前写了一半的东西(从URL来看,去年11月),坚持写完:
—- 跟时髦的分割线 —
最近公司的产品出了一个奇怪的问题,有一个weblogic跑的应用,跑着跑着,就core dump,产生一个40G的core文件。一开始觉得很奇怪,为什么有这么大的一个core,一般就想,嗯,java内存泄露了。但是这个应用的-Xmx一共才4G,加上PermGen,加上JVM的东西,顶多也就5、6G的core啊。再说这个系统总共内存只有32G,40G的core一定是因为某些native library或者其他的什么地方泄露了内存。
Solaris有一些很好的工具,是Linux所没有的,一旦到了Linux平台我就很怀念他们。比如pstack,比如dtrace。尤其是dtrace,加上一些网上的dtrace script,用来troubleshooting真的是很无敌,跟Windows底下的Sysinternals suite一样。不知道是不是Linux也有类似的工具?
pstack可以用来检查一个core文件产生时系统所有线程的状态。(Java也有一个,jstack,有时候不太好用)不过由于我们是内存泄露,当然要用pmap(java有jmap,不过只能查看java heap)。一个正常的java经常的内存image应该是这样:
$ pmap 3536 |more
3536: /opt/middleware/jdk1.6.0_21/bin/amd64/java -Dweblogic.Name=imdmapi -se
0000000000400000 52K r-x-- /opt/middleware/jdk1.6.0_21/bin/amd64/java
000000000041C000 4K rw--- /opt/middleware/jdk1.6.0_21/bin/amd64/java
000000000041D000 158048K rw--- [ heap ]
FFFFFD7ECBCD0000 152K rw--R [ anon ]
FFFFFD7ECC2D6000 152K rw--R [ stack tid=2729 ]
......
FFFFFD7EEA6F1000 8K rw--- /opt/middleware/jdk1.6.0_21/jre/lib/amd64/libnet.so
FFFFFD7EEA6F5000 8K r--s- dev:32,0 ino:477791
FFFFFD7EEA6F8000 16K r--s- dev:32,0 ino:8281559
FFFFFD7EEA7FB000 16K rw--R [ stack tid=8 ]
FFFFFD7EEA800000 1048576K rw--- [ anon ]
FFFFFD7F2A800000 3145728K rw--- [ anon ]
FFFFFD7FEA800000 131072K rw--- [ anon ]
FFFFFD7FF2800000 88064K rw--- [ anon ]
....
FFFFFD7FFF3FD000 8K rwx-- /lib/amd64/ld.so.1
FFFFFD7FFFDFC000 16K rw--- [ stack ] 其中最上面低地址段的是真正的进程的Heap。底下那段红色的anonymous的内存段才是真正的java heap——它其实在内存高端,相当于跟栈在抢内存。这段内存不是用malloc()这样的东西来申请的,而是通过mmap()把一个文件映射到内存里来申请的。我们指定一个4G的max heap,那么JVM就mmap一个4G的文件。这个文件,当然就是/dev/zero。这个行为也是可以观察的,用truss(Linux: strace)指定跟踪mmap何open这两个系统调用就能发现了JVM先open了/dev/zero,然后把这个文件映射进内存。这样还有一个好处是内存相当于已经都memset成0了!至于为什么使用mmap,据说是为了产生一块连续的内存作为heap,不过我不明白为什么pmap显示它还是分成几段。
...