添加For循环可防止OutOfMemoryError [英] Adding For loop prevents OutOfMemoryError

查看:130
本文介绍了添加For循环可防止OutOfMemoryError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我删除for循环时,我得到一个OutOfMemoryError。当我使用for循环时,我没有得到错误。任何人都可以帮助我理解这种行为吗?

When I remove the for loop I get an OutOfMemoryError. When I use for loop I don't get error. Can anyone help me in understanding 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();
    }
}


推荐答案

f()方法在解释帧中执行。解释的帧的行为与JIT编译的帧不同。以下是没有for循环的伪代码的样子:

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

所以你在步骤#3上有 OutOfMemoryError 作为旧 byte [] 数组仍驻留在变量#1中。然而,添加for循环(实际上添加 i 变量)会使事情变得不同:

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

这里当你在步骤#5分配新数组时,第一个数组已经可以被垃圾收集了。

Here when you allocate the new array at step #5, the first array can already be garbage collected.

注意JIT编译器可能表现得更聪明并且取消链接变量中的第一个数组,因为它变得未被使用(在你的特定情况下它根本不会分配它)。

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).

另请注意,在您的特定情况下,结果取决于java编译器。 ECJ(Eclipse编译器)非常聪明,不会将第一个数组存储到变量中,因为它没有被使用。因此,即使没有for循环,您也不会在ECJ编译的类中获得 OutOfMemoryError

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.

有关详细信息,您可以查看 javap 实用程序提供的字节码反汇编输出,看看如何重用变量槽。

For more details you can look into bytecode disassembly output provided by javap utility and see how the variable slots are reused.

这篇关于添加For循环可防止OutOfMemoryError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆