也许有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
我的问题: 第 7 行,堆栈内容为
调用 StringBuilder(String) 后,最后两个参数将被删除,因此堆栈仅包含
这对于正常执行来说是可以的,但是当出现异常(地址14)时,堆栈将如下所示
将异常引用存储在本地变量 2 中之后,因此在 catch 结束时,堆栈上仍然保留了对字符串构建器的引用。
有人可以指出我哪里出错了吗?
谢谢, 冈特
此行为是预期的。你调用了
new StringBuilder(null)
,那么即使抛出了异常,也会有一个 StringBuilder
的实例。
当然,这个对象永远不会(也不能)被操作,因为它没有引用:
sb
是null
。垃圾收集器随时都会收集这个未使用的对象,但 JVM 拥有控制权,你无法预测它的行为。
在这两种情况下,您都应该将 StringBuilder 类放在堆栈顶部(不是它的实例,只是类)。 确保您在“返回”逻辑中将其弹出,而不是在其他地方。
你可以发布一些代码吗?