Java errors from memory

Why is this following code

List<Object> list = new ArrayList<>(); while (true) { for(int i = 0; i < 1000000; i++){ list.add(new Object()); } } 

creates a memory error

But this code is not

 while(true) { List<Object> list = new ArrayList<>(); for(int i = 0; i < 1000000; i++){ list.add(new Object()); } } 

I see that this has something to do with the fact that the list is created either inside the while loop or outside it, obviously, but I'm not sure why this is happening.

+7
java out-of-memory
source share
8 answers

In the first case, you have a single instance of ArrayList , and you continue to add new instances of Object to it until you run out of memory.

In the second case, you create a new ArrayList on each iteration of the while and add 1000000 Object instances to it, which means the ArrayList created in the previous iteration and the 1000000 Object instances it contains can be garbage collected, since the program no longer has links to them.

Note that the second code snippet can also cause a memory error if the new Object is created faster than the garbage collector can release the old ones, but this depends on the implementation of the JVM.

+10
source share

In the first fragment, the list is created (and saved!) Outside the loop, so you just keep adding items to it until you consume all available memory.

In the second snippet, each iteration of the while creates a new ArrayList object. Since you stopped referring to this instance after the iteration is completed, this list has the right to garbage collection, so the old lists continue to be freed, and you will not run out of memory.

+5
source share

In your second case, the created list (and where the elements are added) goes beyond the scope and is eligible for the GC. This will be GCed to make memory for the new ArrayList . Thus, a new ArrayList is created for each iteration, and then it becomes suitable for the GC (when the loop ends). Thus, when memory is low, these objects will be gCed.

In the first case, you add elements to the same ArrayList . Nothing is GCed.

+4
source share

Because when you create a list inside a while loop, your previous list is discarded and you have a new empty list. Subsequently, your memory is freed by the java garbage collector, and you add 1,000,000 items to the list. Then a new list is created and everything repeats.

+3
source share

In the first scenario, the list object is declared outside the while loop, which again works indefinitely (like while (true)), so it continues to add until it runs out of memory, and in the second, because you declared the list inside while, the maximum size is limited by the number of iterations of the for loop.

Each time a for loop exists, the reset list object that is created is new to which you start adding, so you have an upper limit. The old object is garbage collection that cleans up the JVM.

+3
source share

This answer is answered by @Eran, @TheLostMind and that’s all, so I didn’t put one point, I just want to take the opportunity to understand how SoftReference and WeakReference helps to “delay” an exception from memory.

Run the code below with JVM arguments like -Xms64m -Xmx64m to quickly see the results.

 import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Date; import java.util.List; public class OOM { public static void main(String[] args) { System.out.println(new Date()); try { scenario1(false, false); // in my box, OOM occurred with average of 2 seconds. //scenario1(true, false); // in my box, OOM occurred average of 6 seconds. //scenario1(false, true); // in my box, OOM occurred average of 8 seconds. } catch (Exception e) { } catch (Error err){ } System.out.println(new Date()); } private static void scenario1(boolean useSoftReference, boolean useWeakReference) { List<Object> list = new ArrayList<>(); while (true) { for(int i = 0; i < 1000000; i++){ if(useSoftReference){ list.add(new SoftReference<Object>(new Object())); } else if(useWeakReference){ list.add(new WeakReference<Object>(new Object())); } else{ list.add(new Object()); } } } } } 
+3
source share

In the first example, you create a list, add items to it, and then end the loop. In the second example, you create a list, add something to it, then create a new list, add a bunch of things to it and repeat endlessly . Since in the first example, your variable is created outside the loop, there is only 1 list to populate.

+2
source share

The only difference between the two codes is the location of the list List = new ArrayList <> (); line. For the first code, an ArrayList is declared outside the while loop, and it continues to add an infinite number of objects to a single ArrayList instance, so there is a shortage of memory. On the other hand, the second one declares an ArrayList inside the while loop, so it will instantiate a new ArrayList after each loop of the loop (many instances of ArrayList). By the Garbage Collector rule in Java, previous instances of the loop will be deleted since they are no longer specified. As a result, the GC in Java prevents memory shortage in the second case.

+2
source share

All Articles