My application needs about 10 GByte of RAM for specific input, where for regular inputs roughly 1 GByte is enough. Closer analysis with JProfiler reveals that (after GC) quite a lot of memory is used by standard classes from java.util.*
:
LinkedHashMap$Entry
, HashMap$Entry[]
, LinkedHashMap
, HashMap$KeySet
, HashMap$EntrySet
, LinkedHashSet
, TreeMap$Entry
, and TreeMap
(in this order), and related classes. The following entry is of a class in my own code, where the number of instances and the amount of used memory seems very reasonable.
In detail with a total heap usage of about 900 MByte I see the following Size
entries in the All Objects
view:
LinkedHashMap$Entry
: 418 MByte
HashMap$Entry[]
: 178 MByte
LinkedHashMap
: 124 MByte
HashMap$KeySet
: 15 MByte
The memory used by LinkedHashMap
seems to be too high, even when considering that every LinkedHashSet
is backed by a LinkedHashMap
.
I recorded object allocation in JProfiler and observe the Allocation Hot Spots
for LinkedHashMap
. In there, I see entries that I do not understand:
- The third entry shows a hot spot (with 6.5% of the allocated memory) named
X.<init>
where X
is a class in my own code. The constructors of this method do not have anything to do with LinkedHashMap
. Following this entry to Thread.run
at the end shows a slow decline from 6.5% to 5.8% at Thread.run
. What could be the problem with my code in X
? Why is it shown here?
- About 8% of allocated memory is shown in the hot spot named
java.util.HashSet.iterator
. Following this entry along the path with the highest percentage (first entry: 2.8%) I get several methods inside my code until, finally, java.lang.Thread.run
is shown (with 2.8%). What does this mean? As far as I know the Thread.run
method does not create instances of LinkedHashMap
. What is the connection to the iterator
method?
In general, how do I find the code that keeps references to (a lot of) LinkedHashMap
objects? Using the Heap Walker I can only see lots of those instances, but do not see any pattern (even when observing the paths to the GC roots). In my experiments all instances seem to be in order.
Possibly important things:
- My application constructs a result (for further processing) and, for this construction, the high memory usage is observed. The construction continually creates objects, so waiting for a stable point and then observing every single created
LinkedHashMap
object is not possible.
- I have good computers available to debug (up to 48 cores and 192 GByte of RAM, possibly even more).
- java version "1.7.0_13" (Java(TM) SE Runtime Environment (build 1.7.0_13-b20),
Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode))
- JProfiler 7.2.2 (Build 7157), licensed