为什么try-catch语句中JVM ByteCode的LocalVariableTable长度不正确?

问题描述 投票:0回答:1

我写了一个简单的代码:

L11    public void sum2() {
L12        int a = 25;
L13        try {
L14            int b = 8;
L15            if (a > 20) {
L16                int k = a + b;
L17                System.out.println("k=" + k);
L18            }
L19        } catch (Exception e) {
L20            e.printStackTrace();
L21        }
L22    }

我认为变量a的作用域一定是在try语句中,即第15~18行。

但实际上,当我使用 javap 生成字节码时:

      Exception table:
         from    to  target type
             3    41    44   Class java/lang/Exception
      LineNumberTable:
        line 12: 0
        line 14: 3
        line 15: 6
        line 16: 12
        line 17: 16
        line 21: 41
        line 19: 44
        line 20: 45
        line 22: 49
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
           16      25     3     k   I
            6      35     2     b   I
           45       4     2     e   Ljava/lang/Exception;
            0      50     0  this   Lcom/buzz/asm/util/Sum;
            3      47     1     a   I
      StackMapTable: number_of_entries = 3
        frame_type = 252 /* append */
          offset_delta = 41
          locals = [ int ]
        frame_type = 66 /* same_locals_1_stack_item */
          stack = [ class java/lang/Exception ]
        frame_type = 4 /* same */

变量b的范围是第15~21行? (开始=6,结束=41),为什么?

为什么JVM ByteCode的LocalVariableTable不正确?

jvm bytecode local-variables
1个回答
0
投票

这是您的方法的 LocalVariableTable 的细分:

this
是对当前对象的引用,它始终位于槽 0 中并且在整个方法的范围内。

a
位于插槽 1 中,范围从字节码指令 3 到指令 50(整个方法)。

b
位于槽 2 中,范围从指令 6 到指令 41(try 块和以下代码)。

k
位于槽 3 中,范围从指令 16 到指令 41(在 try 块的 if 语句内)。

e
位于槽 2 中,范围为指令 45 到指令 49(catch 块)。

Java 中变量的作用域由声明它的位置决定。在您的代码中,变量

b
是在
try
块内声明的,因此其范围仅限于该块以及嵌套在其中的任何块。

Start
中的
Length
LocalVariableTable
值表示变量所在范围内的字节码指令范围。
Start
值是变量在作用域内的第一个字节码指令的索引,
Length
是变量保留在作用域内的字节码指令的数量。

在您的情况下,

b
位于插槽
2
中,并且在从字节码指令
6
到指令
41
的范围内。此范围包括整个
try
块和以下代码,直到
catch
块的开头。这是因为
catch
块是一个单独的范围,并且
b
不在该范围内。

因此,

b
的范围不仅仅是源代码中的第 15-18 行,而是从其声明延伸到
try
块的末尾,并包含直到
catch 开头的任何其他代码
块。这与 Java 的作用域规则一致,其中变量的作用域是从声明它的点到声明它的块的末尾。

© www.soinside.com 2019 - 2024. All rights reserved.