Does garbage collection immediately after calling Hashmap.remove ()?

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 will happen.
It seems garbage collection does not happen in a loop.
Now I am wondering how to solve the problem.

+6
source share
4 answers

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>

+5
source

You use the same list all the time, which contains 100,000 * 1000 items when the loop exits. To let the GC get rid of your list, you need to reduce its scope within the for(i) loop.

In other words, both the map and the list are available at any time in this code fragment and therefore cannot be compiled.

+5
source

In your case, you continue to populate the same list (even if you remove it from this HashMap, it still exists as a local variable).

JVM promises to do a complete garbage collection before throwing an OutOfMemoryError . Therefore, you can be sure that there is nothing left to clean.

0
source

Your code

 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); } 

coincides with

 List<Integer> list = new ArrayList<Integer>(); for(int i=0;i<100000 * 1000; i++) { list.add(r.nextInt(100000)); } 

As you can see its List, not a map that stores all integers. Try this instead and see what happens;)

 list.add(r.nextInt(128)); 
0
source

All Articles