当前位置: 首页 > 面试题库 >

当看似无关的代码块被注释掉时,出现OutOfMemoryError

南门志
2023-03-14
问题内容

有人可以解释为什么OutOfMemoryErrorfor注释掉循环后该程序会抛出a 吗?如果不加注释,则可以正常运行。

抛出的异常是:

线程“主”中的异常java.lang.OutOfMemoryError:Java堆空间

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

问题答案:

我研究了许多不同类型的代码片段,可以将它们插入您的注释所在的位置,并且唯一不会导致的OutOfMemoryError代码类型是将一些值分配给局部变量的代码。

这是对我来说最有意义的解释:

当你有

byte[] data = new byte[dataSize];

该字节码指令是

    12: newarray       byte
    14: astore_1

在哪里newarray创建一个新数组并将astore_1对它的引用存储在局部变量1。

此后,该变量的作用域丢失,但是字节码没有说明清除其值的任何内容,因此在堆栈帧中保留了对该对象的引用。即使代码本身无法达到此特定的垃圾收集器,它也可以实现。

如果相反,您尝试分配另一个局部变量,例如

byte i = 1;

那么相应的字节码指令就像

    15: iconst_1      
    16: istore_1

其中iconst_1将值1存储在堆栈上,并将istore_1该值存储在变量1中,该变量似乎与以前相同。如果是,则您将覆盖它的值,对该byte[]对象的引用将丢失,然后该对象“成为”有资格进行垃圾回收。

最终证明

使用-g选项编译此代码

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

}

然后运行javap -c -l Driver。你会看到LocalVariableTable这样的

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

其中槽是在索引中astore_1istore_1。因此,byte[]当您为局部变量分配新值时,对的引用将被清除。即使变量具有不同的类型/名称,它们也以字节码形式存储在同一位置。



 类似资料:
  • 问题内容: 我想知道Vim中是否有任何键映射可以让我缩进某些代码行(无论这些行是在可视模式下选择的,还是在当前光标位置上方/下方的 n 行)。 所以基本上是可以转换以下内容的东西 至 我可以使用或注释掉相关行。理想情况下,如果给定的行已被注释掉,我也希望使用相同的键盘映射来取消注释。 问题答案: 步骤1: 转到要评论的第一行的第一列。 步骤2: 按:+,然后选择要注释的行: 步骤3: - spac

  • 问题内容: 是否有一种机制可以注释掉大量的Python代码? 现在,我能看到的注释掉代码的唯一方法是用a开头每一行,或者用三引号将代码括起来。 这些问题是,在每一行之前插入都很麻烦,并使要用作注释的字符串显示在生成的文档中。 阅读所有评论后,答案似乎是“否”。 问题答案: Python没有这种机制。在每行前面加a可以阻止评论。有关更多信息,请参阅PEP 8 。大多数Python IDE支持一种为您

  • 我一直在从WebStorm和Rubymine转移到Atom,我真的很想念Jet大脑编辑器的一个功能,在这个功能中,您可以选择一个代码块,然后按CMD-,它会在开始时添加特定语言的注释字符每一行。(为ruby。为js,为css等)。 Atom是否有内置的快捷方式或提供此功能的软件包?

  • 问题内容: NetBeans中是否有用于突出显示代码块并对其进行注释/取消注释的快捷方式? 问题答案: 键盘快捷键列表可以在NetBeans Wiki中找到。 打开/关闭搜索结果突出显示 + + 添加/删除评论。 应该适用于所有语言 + 或在Mac +中

  • 问题内容: 是否可以注释代码块?例如循环还是大括号?如果是这样,怎么办? 第一.java ForCycle.java 根据http://www.javacodegeeks.com/2012/11/java-annotations-tutorial-with-custom- annotation.html @Target –指示注释类型适用的程序元素的种类。一些可能的值是TYPE,METHOD,CO

  • 本文向大家介绍jsp输出当前时间的实现代码,包括了jsp输出当前时间的实现代码的使用技巧和注意事项,需要的朋友参考一下 在jsp页面中输出完整的时间,格式为"年 月 日  时:分:秒" 以上就是小编为大家带来的jsp输出当前时间的实现代码全部内容了,希望大家多多支持呐喊教程~