GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing github.com — java-interview/code/HashMapMemoryLeak.java at master · bootsrc/java-interview Expand file tree/ Copy pathHashMapMemoryLeak.javaMore file actions 163 lines (130 loc) · 5.21 KB / Copy pathHashMapMemoryLeak.javaFile metadata and controls163 lines (130 loc) · 5.21 KB 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 import java.util.HashMap; import java.util.Map; /** * 演示HashMap的内存泄漏产生过程, 参考test()方法 */ public class HashMapMemoryLeak { public static void main(String[] args) { // test1(); test2(); } private static void test1() { Map<Person, Integer> map = new HashMap<Person, Integer>(); Person p = new Person("zhangsan", 12); System.out.println("step1 p=" + p); System.out.println("System.identityHashCode(p)=" + System.identityHashCode(p)); map.put(p, 1); p.setName("lisi"); // 因为p.name参与了hash值的计算,修改了之后hash值发生了变化,所以下面删除不掉 System.out.println("System.identityHashCode(p)=" + System.identityHashCode(p)); map.remove(p); System.out.println("step2 p=" + p); System.out.println("hashCOde" + p.hashCode()); System.out.println("---------After remove()-------"); System.out.println("map.size() " + map.size()); System.out.println("map.containsKey(p) " + map.containsKey(p)); System.out.println("map.get(p) " + map.get(p)); } private static void test2() { Map<Person, Integer> map = new HashMap<Person, Integer>(); Person p = new Person("zhangsan", 12); map.put(p, 1); System.out.println("map.get(p)="+ map.get(p)); Person p2 = new Person("zhangsan", 13); System.out.println("p.hashCode() == p2.hashCode() ? " + (p.hashCode() == p2.hashCode())); System.out.println("p.equals(p2) " + p.equals(p2)); System.out.println("map.size() " + map.size()); System.out.println("map.get(p)="+ map.get(p)); System.out.println("map.get(p2)="+ map.get(p2)); // 在setName之前,假设p对应的KV对存放的位置是X p.setName("lisi"); // 这里造成p2这个key的数据内存泄漏。导致后面无法被删除掉 // p.setName("lisi")后, 这个Node存放的Entry的未知不变,但是,里面Node里面的Key的name变里,导致key的hashCode()变了。 // 后面通过map.get(p)去检索数据的时候,p.hashCode()变了,经过hash计算后得到位置是Y(Y此时为空) // 所以这时候map.get(p)返回null, map.containsKey(p)返回false // 所以位置X处的Node数据已经无法进行get() ,put(),containsKey(), remove()的操作了 // 这个内存因为被HashMap引用,也无法GC, // 这快内存不能被删也不能鄂博查询,也不能被GC回收,称之为内存泄漏(memory leak) // 这才几个字节的内存泄漏,还不会出事故, 大量的内存泄漏,会浪费很多内存,降低系统性能。最终浪费大量的堆内存, // 最终导致内存溢出(Out of memory, OutOfMemoryException, 或者报错Heap Space...) // 结论: 大量的内存泄漏会最终导致内存溢出。 如果出现了内存溢出的报错,我们可以去查看代码,是否有内存泄漏, // 或者到map里查看是否有一些无意义的垃圾数据(极有可能是内存溢出的数据) map.remove(p); // map.remove(p2); System.out.println("---------After map.remove(p)-------------"); System.out.println("map.size() " + map.size()); System.out.println("map.get(p)="+ map.get(p)); System.out.println("map.get(p2)="+ map.get(p2)); } } class Person { private String name; private int age; public Person(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } // @Override // public boolean equals(Object obj) { // return super.equals(obj); // } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (obj instanceof Person) { Person personValue = (Person)obj; if (personValue.getName() == null && name ==null) { return true; } if (personValue.getName() != null && personValue.getName().equals(name)){ return true; } } return false; } // @Override // public boolean equals(Object obj) { // if (obj == null) { // return false; // } // // if (obj instanceof Person) { // Person personValue = (Person)obj; // // if (personValue.getName() == null && name ==null && personValue.getAge() ==age) { // return true; // } // // if (personValue.getName() != null && personValue.getName().equals(name) && personValue.getAge() ==age){ // return true; // } // } // // return false; // } // @Override // public boolean equals(Object obj) { // if (obj == null) { // return false; // } // // return hashCode() == obj.hashCode(); // } @Override public int hashCode() { return name.hashCode() * 123; } } |
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |