When I remove the for-loop I get an OutOfMemoryError
. When I use for-loop I don't get any error.
Can anyone help me to understand this behavior?
public class JavaMemoryPuzzlePolite { private final int dataSize = (int) (Runtime.getRuntime().maxMemory() * 0.6); public void f() { { System.out.println(dataSize); byte[] data = new byte[dataSize]; } for (int i = 0; i < 1; i++) { System.out.println("Please be so kind and release memory"); } System.out.println(dataSize); byte[] data2 = new byte[dataSize]; } public static void main(String[] args) { JavaMemoryPuzzlePolite jmp = new JavaMemoryPuzzlePolite(); jmp.f(); } }
OutOfMemoryError: Java heap space. 1) An easy way to solve OutOfMemoryError in java is to increase the maximum heap size by using JVM options "-Xmx512M", this will immediately solve your OutOfMemoryError.
OutOfMemoryError exception. Usually, this error is thrown when there is insufficient space to allocate an object in the Java heap. In this case, The garbage collector cannot make space available to accommodate a new object, and the heap cannot be expanded further.
The f()
method is executed in interpreted frame. Interpreted frames behave differently than JIT-compiled frames. Here's how it looks in pseudocode without the for loop:
1. Allocate dataSize bytes of memory 2. Store it into variable slot #1 3. Allocate dataSize bytes of memory 4. Store it into variable slot #1
So you have the OutOfMemoryError
on the step #3 as the old byte[]
array still resides in variable #1. However adding the for loop (actually adding an i
variable) makes thing different:
1. Allocate dataSize bytes of memory 2. Store it into variable slot #1 3. Store 0 to slot #1 (thus byte[] array is now eligible for GC) 4. Do the for loop 5. Allocate dataSize bytes of memory 6. Store it into variable slot #2
Here when you allocate the new array at step #5, the first array can already be garbage collected.
Note that JIT compiler may behave smarter and unlink the first array from the variable as it becomes unused (in your particular case it will not allocate it at all).
Also note that in your particular case the result depends on java compiler. ECJ (Eclipse compiler) is smart enough not to store the first array into variable at all as it's not used. Thus you will not get OutOfMemoryError
in ECJ-compiled class even without the for loop.
For more details you can look into bytecode disassembly output provided by javap
utility and see how the variable slots are reused.
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