The Java code is as follows:
Random r = new Random(1234697890);
HashMap<Integer, List<Integer>> map = new HashMap<Integer, List<Integer>>();
List<Integer> list = new ArrayList<Integer>();
for(int i=0;i<100000;i++){
for(int j=0;j<1000;j++){
list.add(r.nextInt(100000));
}
map.put(i, list);
map.remove(i);
}
when i
reaches 37553 , java.lang.OutOfMemoryError: Java heap space
happens.
It seems that garbage collection does not happen in the loop.
Now I wonder how to fix the problem.
Try rewriting the code as follows and you should not get OOME's ...
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 original code is that:
Moving the list
declaration inside the loop means that a new ArrayList
is created and filled in each loop iteration, and becomes garbage when you start the next iteration.
Someone suggested calling System.gc()
. It won't help at all in your case because there is minimal1 garbage to be collected. And in general it is a bad idea because:
System.gc()
may be totally ignored anyway. The JVM can be configured so that calls to System.gc()
are ignored.1 - The pedant in me would like to point out that map.put(i, list); map.remove(i);
is most likely generating an Integer
object that most likely becomes garbage. However, this is "chicken feed" compared to your indefinitely growing ArrayList
object.
You use the same List all the time, which contains 100000 * 1000 items when the loop exits. To enable GC to get rid of your list, you need to reduce its scope to within the for(i)
loop.
In other words, both map and list are reachable at all time in that piece of code and are therefore not eligible for collection.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With