当构造函数中出现异常时,java编译器出错

当构造函数中出现异常时,java编译器出错,java,exception,compiler-construction,constructor,Java,Exception,Compiler Construction,Constructor,也许有一位java内部构件专家。 我在理解以下java代码的编译代码时遇到问题 public class TestException { public static void main(String[] args) { StringBuilder sb = null; try { sb = new StringBuilder(null); } catch (NullPointe

也许有一位java内部构件专家。 我在理解以下java代码的编译代码时遇到问题

public class TestException
{
    public static void main(String[] args)
    {
        StringBuilder sb = null;
        try
        {
            sb = new StringBuilder(null);
        }
        catch (NullPointerException t)
        {

        }
        if (sb != null)
        {
            System.out.print(sb.toString());
        }
    }
}
这将被编译为:

stack=3, locals=3, args_size=1

 0: aconst_null   
 1: astore_1 
 2: new           #2                  // class java/lang/StringBuilder
 5: dup           
 6: aconst_null   
 7: invokespecial #3                  // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
10: astore_1      
11: goto          15
14: astore_2  
15: aload_1       
16: ifnull        29
19: getstatic     #5                  // Field java/lang/System.out:Ljava/io/OutStream;
22: aload_1       
23: invokevirtual #6                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
26: invokevirtual #7                  // Method java/io/OutStream.print:(Ljava/lang/String;)V
29: return

Exception table:
 from    to  target type
     2    11    14   Class java/lang/NullPointerException
stack=3,locals=3,args\u size=1
0:aconst_null
1:astore_1
2:new#2//类java/lang/StringBuilder
5:dup
6:aconst_null
7:invokespecial#3//方法java/lang/StringBuilder。”“:(Ljava/lang/String;)V
10:astore_1
11:goto 15
14:astore_2
15:aload_1
16:ifnull 29
19:getstatic#5//fieldjava/lang/System.out:Ljava/io/OutStream;
22:aload_1
23:invokevirtual#6//方法java/lang/StringBuilder.toString:()Ljava/lang/String;
26:invokevirtual#7//方法java/io/OutStream.print:(Ljava/lang/String;)V
29:返回
例外情况表:
从到目标类型
2 11 14类java/lang/NullPointerException
我的问题是: 在第7行,堆栈内容为

  • 引用StringBuilder实例
  • 引用StringBuilder实例
  • 空的
  • 调用StringBuilder(String)后,最后两个参数将被删除,因此堆栈只包含

  • 引用StringBuilder实例
  • 这对于正常执行来说是可以的,但当出现异常(地址14)时,堆栈将如下所示

  • 引用StringBuilder实例
  • 引用异常实例
  • 在本地var 2中存储了异常ref之后,所以在catch结束时,仍然有对stringbuilder的ref留在堆栈上

    有人能指出我哪里出错了吗

    谢谢,
    冈特

    这种行为是意料之中的。您调用了
    new StringBuilder(null)
    ,则存在
    StringBuilder
    的实例,即使引发了异常


    当然,这个对象永远不会(也不能)被操纵,因为它没有引用:
    sb
    is
    null
    。垃圾收集器将随时收集此未使用的对象,但JVM拥有控制权,您无法预测其行为。

    在这两种情况下,您都应该将StringBuilder类放在堆栈顶部(不是它的实例,只是类)。确保在“返回”逻辑中弹出它,而不是在其他地方


    您可以发布一些代码吗?

    您是否打算不在堆栈上使用字符串生成器?它仍然在范围内,所以它应该在那里。请参阅我对下面答案的评论。。。枪械问题不是“死”的问题。我试图编写一个jvm,由于这种行为,我遇到了堆栈超出估计范围的问题。(我已经编写了一个小型测试程序,其中我不止一次遇到过这种情况)。“真正的”java似乎没有受到干扰,如果我把代码放在一个无止境的循环中,它永远不会产生错误……我认为您必须在JVM中处理这种类型的问题。这是你写的任务。我想象不出你对这条线还有什么期待。是的。只有对实例的引用。在本例中(尽可能多),我认为它是对类实例的引用,而不是对StringBuilder实例的引用。这两种方式都不重要,你需要确保你一直都在从堆栈中弹出它们,不管是否有异常。你好,Ted,澄清一下:堆栈上只有引用(引用实例…)。发布一些(虚拟机的)代码似乎不是很有帮助,因为这必须占虚拟机代码总数的80%。我的问题是,当我对生成的java代码的解释没有失败时,在处理异常以“消除”不必要的引用时会出现一种特殊情况。否则,堆栈可能会增长到估计大小以上。