我写的平台,为每个模块提供了一个父类,当中有一个消息队列是用LinkedBlockingQueue实现的,存在很严重的内存泄露。
分析代码,发现,调用最为频繁的是这一段代码:
while (true) {
..................
msg = (TaskMsg) m_tb.queue_.poll(100,TimeUnit.MILLISECONDS);
...........
}
在没有消息的情况下,每个模块每秒钟会调用Poll函数10次(1秒除以100毫秒)。于是,在jbuilder2006下测试了这个函数,观察gc日志,果不其然,令人欣慰的一幕出现了:
[GC 512K->232K(1984K), 0.0039062 secs]
[GC 744K->442K(1984K), 0.0024386 secs]
[GC 954K->652K(1984K), 0.0015416 secs]
[GC 1164K->862K(1984K), 0.0012926 secs]
[GC 1374K->1072K(1984K), 0.0014093 secs]
。。。。。。。。。。。。。。。。。。。。
这个函数存在内存泄露,每调用1万次,会泄露312K内存。后来测试发现,只有在JDK1.5下有内存泄露,而在JDK1.6下,GC日志显示,这个函数没有泄露:
[GC 896K->215K(5056K), 0.0029709 secs]
[GC 1111K->215K(5056K), 0.0008942 secs]
[GC 1111K->215K(5056K), 0.0003455 secs]
[GC 1111K->215K(5056K), 0.0001933 secs]
。。。。。。。。。。。。。。
于是,我在JDK1.5环境加载一个模块,这个模块不做任何事情,限制内存42M,1002秒后,模块因为内存不够崩溃,gc日志:
。。。。。。。。。。。。。
0.066: [Full GC 730K->730K(41664K), 0.0323995 secs]
0.099: [Full GC 730K->627K(42688K), 0.0386444 secs]
4.953: [Full GC 42281K->39992K(42688K), 0.0811821 secs]
5.938: [Full GC 42687K->40780K(42688K), 0.1345104 secs]
7.547: [Full GC 42687K->41747K(42688K), 0.1410599 secs]
125.547: [Full GC 42687K->41885K(42688K), 0.1583355 secs]
429.919: [Full GC 42687K->42071K(42688K), 0.1803768 secs]
568.374: [Full GC 42688K->42155K(42688K), 0.2544925 secs]
774.676: [Full GC 42688K->42281K(42688K), 0.1433841 secs]
912.935: [Full GC 42687K->42365K(42688K), 0.1431487 secs]
1034.963: [Full GC 42687K->42440K(42688K), 0.1457875 secs]
1035.111: [Full GC 42440K->42440K(42688K), 0.2028878 secs]
1435.741: [Full GC 42687K->42685K(42688K), 0.2041293 secs]
1435.948: [Full GC 42685K->42685K(42688K), 0.1681726 secs]
1438.172: [Full GC 42688K->42686K(42688K), 0.1547281 secs]
1438.329: [Full GC 42686K->42686K(42688K), 0.1533963 secs]
1439.510: [Full GC 42687K->42687K(42688K), 0.1537239 secs]
。。。。。。。。。。。。
而JDK1.6下,3600秒后模块依然正常,gc日志显示,内存达到41888K后就不变了:
。。。。。。。。。。。
2334.178: [Full GC 42687K->41888K(42688K), 0.1302688 secs]
2636.473: [Full GC 42687K->41889K(42688K), 0.1334375 secs]
2938.790: [Full GC 42687K->41888K(42688K), 0.1462437 secs]
2938.953: [Full GC 42367K->41888K(42688K), 0.1297961 secs]
3242.218: [Full GC 42687K->41888K(42688K), 0.1493409 secs]
3544.285: [Full GC 42687K->41889K(42688K), 0.1619370 secs]
3682.247: [Full GC 42687K->41888K(42688K), 0.1322534 secs]
。。。。。。。。
综合上面的情况,基本得到结论,基本是因为使用JDK1.5而发生内存泄露。
根据sun公司的http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=2143840可以看出在jdk5u11和jdk6u1的老版本中确实存在这个问题,jdk5-12,jdk6-2应该就能修正了