Typical memory leak problems and solutions in Java
- 2020-04-01 03:20:52
- OfStack
Q: how can memory leaks occur in Java?
A: there are many reasons for memory leaks in Java. A typical example is one that does not implement hasCode and
The case where the Key class of the equals method is saved in a HashMap. You end up with a lot of duplicate objects. All memory leaks
The OutOfMemoryError exception will be thrown at the end, and the memory leak will be simulated by an infinite loop for a short time
Let me give you an example.
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);
}
}
The results are as follows:
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: how to solve the memory leak above?
A: implement the equals and hasCode methods of the Key class.
.....
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();
}
}
.....
Reexecuting the program results in the following:
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: how do you find memory leaks in a real scenario?
A: get the thread ID with the following code
C:>jps
5808 Jps
4568 MemoryLeak
3860 Main
Open jconsole from the command line
C:>jconsole 4568
The Key class that implements hasCode and equals and the graph that does not are shown below:
No memory leaks:
< img SRC = "border = 0 / / files.jb51.net/file_images/article/201404/201442883416065.jpg? 201432883453 ">
Memory leak:
< img SRC = "border = 0 / / files.jb51.net/file_images/article/201404/201442883646109.jpg? 201432883656 ">