LocalVariableTable 缺少什么?

What is missing in LocalVariableTable?

给定一个简单的 try-catch-finally 方法:

public void t() {
    try {
        f1();
    }catch(Exception e) {
        f2();
    }finally {
        f3();
    }
}

用"javac -g"编译成:

public void t();
  descriptor: ()V
  flags: ACC_PUBLIC
  Code:
stack=1, locals=3, args_size=1
   0: aload_0
   1: invokespecial #15                 // Method f1:()V
   4: goto          26
   7: astore_1
   8: aload_0
   9: invokespecial #18                 // Method f2:()V
  12: aload_0
  13: invokespecial #21                 // Method f3:()V
  16: goto          30
  19: astore_2
  20: aload_0
  21: invokespecial #21                 // Method f3:()V
  24: aload_2
  25: athrow
  26: aload_0
  27: invokespecial #21                 // Method f3:()V
  30: return
Exception table:
   from    to  target type
       0     4     7   Class java/lang/Exception
       0    12    19   any
LineNumberTable:
  line 7: 0
  line 8: 4
  line 9: 8
  line 11: 12
  line 10: 19
  line 11: 20
  line 12: 24
  line 11: 26
  line 13: 30
LocalVariableTable:
  Start  Length  Slot  Name   Signature
      0      31     0  this   Lsample/Sample;
      8       4     1     e   Ljava/lang/Exception;
StackMapTable: number_of_entries = 4
  frame_type = 71 /* same_locals_1_stack_item */
    stack = [ class java/lang/Exception ]
  frame_type = 75 /* same_locals_1_stack_item */
    stack = [ class java/lang/Throwable ]
  frame_type = 6 /* same */
  frame_type = 3 /* same */

注意locals=3,但LocalVariableTable 中只有两项。字节码第 19 行(astore_2)和第 24 行(aload_2)表示第三个局部变量确实存在。

问题是:第三个局部变量是什么,为什么在LocalVariableTable中漏掉了?

第三个局部变量是finally块的实现细节。如果您的 try/catch 抛出一个变量,它必须临时存储异常,以便它可以在重新抛出之前调用 f3(),这就是插槽 2 正在做的事情。