I am facing a strange issue of memory leak. As I am new to memory leak resolution, I need some help.
Consider the below code
for ( Map.Entry<String, HashMap<String, Object>> entry :memtable.RBTree.entrySet()) {
bufferedWriter.write(entry.getKey() + "," + entry.getValue());
bufferedWriter.newLine();
}
Note - memtable.RBTree.entrySet() - It has 10,000 entries. It is skiplist data structure.
Now the problem is this line
bufferedWriter.write(entry.getKey() + "," + entry.getValue());
Here, as entry.getValue()
is the HashMap
, I am seeing huge amount of heap memory consumption ( like approx 3GB of heap )
However when I simple do this - bufferedWriter.write(entry.getKey() + "," + "DUMMY STRING");
Here, I have replaced HashMap
with just a dummy string - Here I am seeing my program is running like a wind ( just in 600 MB heap )
I am not able to figure out why entry.getValue() - hashmap
is causing the memory leak while just concatenating with some random string is not.
Any help would be appreciated.
1 Answer 1
The memory usage is probably the use of entry.getValue().toString()
. You could check sizes of the maps by changing the line to confirm quite how large the strings are:
bufferedWriter.write(entry.getKey() + "," + entry.getValue().length());
With a top level map of 10,000 keys, and each of which is a sizable sub-map you will easily end up creating a lot of potentially very long String
of the form:
"originalkey1,{subkey1=value1, .... subkeyNNN=valueNNN}"
...
"originalkey10000,{subkeyA=valueA, .... subkeyXXX=valueXXX}"
These aren't memory leaks as such - they would be garbage collectable after use but would contribute to the heavy footprint when compared to your dummy line.
If memory footprint is a concern, replace the write by multiple lines which output the entry.getValue()
components directly to the stream rather than implicitly appending as massive String, for example:
bufferedWriter.write(entry.getKey());
bufferedWriter.write(",{");
// iterate the sub-map here and write
bufferedWriter.write("}");