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);
}
}
怎么解决上面的内存泄露?
实现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();
}
}
在实际场景中,怎么查找内存泄露?
通过以下代码获取线程ID
C:\>jps
5808 Jps
4568 MemoryLeak
3860 Main
通过命令行打开jconsole
C:\>jconsole 4568