a:java中,造成内存泄露的原因有很多种。典型的例子是一个没有实现hascode和
equals方法的key类在hashmap中保存的情况。最后会生成很多重复的对象。所有的内存泄露
最后都会抛出outofmemoryerror异常,下面通过一段简短的通过无限循环模拟内存泄露
的例子说明一下。
import java.util.hashmap; import java.util.map; public class memoryleak { public static void main(string[] args) { map<key, string> map = new hashmap<key, string>(1000); int counter = 0; while (true) { // creates duplicate objects due to bad key class map.put(new key("dummykey"), "value"); counter++; if (counter % 1000 == 0) { system.out.println("map size: " + map.size()); system.out.println("free memory after count " + counter + " is " + getfreememory() + "mb"); sleep(1000); } } } // inner class key without hashcode() or equals() -- bad implementation static class key { private string key; public key(string key) { this.key = key; } } //delay for a given period in milli seconds public static void sleep(long sleepfor) { try { thread.sleep(sleepfor); } catch (interruptedexception e) { e.printstacktrace(); } } //get available memory in mb public static long getfreememory() { return runtime.getruntime().freememory() / (1024 * 1024); } }
结果如下:
map size: 1000 free memory after count 1000 is 4mb map size: 2000 free memory after count 2000 is 4mb map size: 1396000 free memory after count 1396000 is 2mb map size: 1397000 free memory after count 1397000 is 2mb map size: 1398000 free memory after count 1398000 is 2mb map size: 1399000 free memory after count 1399000 is 1mb map size: 1400000 free memory after count 1400000 is 1mb map size: 1401000 free memory after count 1401000 is 1mb ..... ..... map size: 1452000 free memory after count 1452000 is 0mb map size: 1453000 free memory after count 1453000 is 0mb exception in thread "main" java.lang.outofmemoryerror: java heap space at java.util.hashmap.addentry(hashmap.java:753) at java.util.hashmap.put(hashmap.java:385) at memoryleak.main(memoryleak.java:10)
q:怎么解决上面的内存泄露?
a:实现key类的equals和hascode方法。
..... static class key { private string key; public key(string key) { this.key = key; } @override public boolean equals(object obj) { if (obj instanceof key) return key.equals(((key) obj).key); else return false; } @override public int hashcode() { return key.hashcode(); } } .....
重新执行程序会得到如下结果:
map size: 1 free memory after count 1000 is 4mb map size: 1 free memory after count 2000 is 4mb map size: 1 free memory after count 3000 is 4mb map size: 1 free memory after count 4000 is 4mb ... free memory after count 73000 is 4mb map size: 1 free memory after count 74000 is 4mb map size: 1 free memory after count 75000 is 4mb
q:在实际场景中,你怎么查找内存泄露?
a:通过以下代码获取线程id
c:\>jps 5808 jps 4568 memoryleak 3860 main
通过命令行打开jconsole
c:\>jconsole 4568
实现了hascode和equals的key类和没有实现的图表如下所示:
没有内存泄露的:
造成内存泄露的:
更多java中典型的内存泄露问题和解决方法。