java内存泄漏的经典案例
这篇文章主要介绍了Java中典型的内存泄露问题和解决方法,典型的内存泄露例子是一个没有实现hasCode和 equals方法的Key类在HashMap中保存的情况,可以通过实现Key类的equals和hasCode方法解决这种内存泄漏问题,需要的朋友可以参考下。
Q:在Java中怎么可以产生内存泄露?
A:Java中,造成内存泄露的原因有很多种。典型的例子是一个没有实现hasCode和
equals方法的Key类在HashMap中保存的情况。最后会生成很多重复的对象。所有的内存泄露
最后都会抛出OutOfMemoryError异常,下面通过一段简短的通过无限循环模拟内存泄露
的例子说明一下。
1 import java.util.HashMap; 2 import java.util.Map; 3 4 public class MemoryLeak { 5 6 public static void main(String[] args) { 7 Map<Key, String> map = new HashMap<Key, String>(1000); 8 9 int counter = 0; 10 while (true) { 11 // creates duplicate objects due to bad Key class 12 map.put(new Key("dummyKey"), "value"); 13 counter++; 14 if (counter % 1000 == 0) { 15 System.out.println("map size: " + map.size()); 16 System.out.println("Free memory after count " + counter 17 + " is " + getFreeMemory() + "MB"); 18 19 sleep(1000); 20 } 21 22 23 } 24 } 25 26 // inner class key without hashcode() or equals() -- bad implementation 27 static class Key { 28 private String key; 29 30 public Key(String key) { 31 this.key = key; 32 } 33 34 } 35 36 //delay for a given period in milli seconds 37 public static void sleep(long sleepFor) { 38 try { 39 Thread.sleep(sleepFor); 40 } catch (InterruptedException e) { 41 e.printStackTrace(); 42 } 43 } 44 45 //get available memory in MB 46 public static long getFreeMemory() { 47 return Runtime.getRuntime().freeMemory() / (1024 * 1024); 48 } 49 50 } 51 结果如下: 52 复制代码 代码如下: 53 54 map size: 1000 55 Free memory after count 1000 is 4MB 56 map size: 2000 57 Free memory after count 2000 is 4MB 58 map size: 1396000 59 Free memory after count 1396000 is 2MB 60 map size: 1397000 61 Free memory after count 1397000 is 2MB 62 map size: 1398000 63 Free memory after count 1398000 is 2MB 64 map size: 1399000 65 Free memory after count 1399000 is 1MB 66 map size: 1400000 67 Free memory after count 1400000 is 1MB 68 map size: 1401000 69 Free memory after count 1401000 is 1MB 70 ..... 71 ..... 72 map size: 1452000 73 Free memory after count 1452000 is 0MB 74 map size: 1453000 75 Free memory after count 1453000 is 0MB 76 Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 77 at java.util.HashMap.addEntry(HashMap.java:753) 78 at java.util.HashMap.put(HashMap.java:385) 79 at MemoryLeak.main(MemoryLeak.java:10)
Q:怎么解决上面的内存泄露?
A:实现Key类的equals和hasCode方法。
1 ..... 2 static class Key { 3 private String key; 4 5 public Key(String key) { 6 this.key = key; 7 } 8 9 10 @Override 11 public boolean equals(Object obj) { 12 13 if (obj instanceof Key) 14 return key.equals(((Key) obj).key); 15 else 16 return false; 17 18 } 19 20 @Override 21 public int hashCode() { 22 return key.hashCode(); 23 } 24 } 25 .....
重新执行程序会得到如下结果:
1 map size: 1 2 Free memory after count 1000 is 4MB 3 map size: 1 4 Free memory after count 2000 is 4MB 5 map size: 1 6 Free memory after count 3000 is 4MB 7 map size: 1 8 Free memory after count 4000 is 4MB 9 ... 10 Free memory after count 73000 is 4MB 11 map size: 1 12 Free memory after count 74000 is 4MB 13 map size: 1 14 Free memory after count 75000 is 4MB
Q:在实际场景中,你怎么查找内存泄露?
A:通过以下代码获取线程ID
1 C:\>jps 2 5808 Jps 3 4568 MemoryLeak 4 3860 Main
通过命令行打开jconsole
1 C:\>jconsole 4568
实现了hasCode和equals的Key类和没有实现的图表如下所示:
没有内存泄露的:
造成内存泄露的:
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步