Try rewriting the code like this and you should not get OOME ...
Random r = new Random(1234697890); HashMap<Integer, List<Integer>> map = new HashMap<Integer, List<Integer>>(); for(int i=0;i<100000;i++){ List<Integer> list = new ArrayList<Integer>(); for(int j=0;j<1000;j++){ list.add(r.nextInt(100000)); } map.put(i, list); map.remove(i); }
The problem with your source code is this:
- you create only one list,
- you keep adding more and more elements to it and
- this list only becomes garbage when the code exits ... because it is "in the field" all the time.
Moving the list declaration inside the loop means that a new ArrayList is created and populated in each iteration of the loop and becomes garbage when the next iteration starts.
Someone suggested calling System.gc() . This will not help at all in your case, because there is minimal garbage to be collected. In general, this is a bad idea, because:
- GC is guaranteed to start just before OOME is released,
- The JVM can better understand than you can, when is the best (i.e. most effective) time to launch the GC,
- your call to
System.gc() can be completely ignored. The JVM can be configured so that calls to System.gc() ignored.
1 - The pedant in me would like to indicate that map.put(i, list); map.remove(i); map.put(i, list); map.remove(i); most likely generates an Integer object, which most likely becomes garbage. However, this is โchicken feedโ compared to your infinitely growing ArrayList .Sub>
source share