Java – outofmemoryerror commented out from seemingly unrelated code blocks

Can anyone explain why the program throws an outofmemoryerror when the for loop is commented out? If it is uncommented, it works normally

The exception thrown is:

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

Solution

I have investigated this with many different types of code snippets that can be inserted into your comments, and the only code type that does not cause outofmemoryerror is the code that assigns a value to a local variable

This is the most meaningful explanation for me:

When you have

byte[] data = new byte[dataSize];

Bytecode instructions yes

12: newarray       byte
    14: astore_1

Newarray creates a new array, astore_ 1 stores a reference to it in the local variable 1

After that, the range of the variable is lost, but the bytecode does not specify anything whose value is cleared, so there is a reference to the object remaining in the stack frame This particular garbage collector believes that it can be accessed even if the code itself cannot access it

Instead, if you try to assign another local variable, such as

byte i = 1;

Then the corresponding bytecode instruction is like

15: iconst_1      
    16: istore_1

Where iconst_ 1 stores the value 1 on the stack, while iStore_ 1 stores the value in variable 1, which appears to be the same as the previous variable If so, you will overwrite its value, the reference to byte [] object will be lost, and then the object "becomes" eligible for garbage collection

Final proof

Compile this code with the - G option

public class Driver {
    private static final int dataSize = (int) (Runtime.getRuntime().maxMemory() * 0.6);

    public static void main(String[] args) throws InterruptedException {
        {
            System.out.println(dataSize);
            byte[] data = new byte[dataSize];

        }
        byte i = 1;
        System.out.println(dataSize);
        byte[] data2 = new byte[dataSize];
    }

}

Then run javap - C - L driver You will see a localvariabletable like this

LocalVariableTable:
  Start  Length  Slot  Name   Signature
   15       0     1    data   [B
    0      33     0    args   [Ljava/lang/String;
   17      16     1     i     B
   32       1     2    data2  [B

Where slot is astore_ 1 and iStore_ Index in 1 So you see, when you assign a new value to a local variable, you clear the reference to byte [] Even if variables have different types / names, they are stored in the same place in bytecode

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>