Compiler construction Java-don';在调试过程中,如果没有对变量进行初始化,则无法看到该变量

Compiler construction Java-don';在调试过程中,如果没有对变量进行初始化,则无法看到该变量,compiler-construction,jvm,stack,Compiler Construction,Jvm,Stack,给定jdk6中Java中的以下方法 public void test(){ Integer i; try{ i = 9; } catch (Exception ex){ //nothing } int something = 1; //Breakpoint here } 当我停在断点时,我根本看不到堆栈上的变量“I”,即使一步一步地走,我看到try块中分配了9 public void test(){ Integer i = null; try{ i = 9; } catch

给定jdk6中Java中的以下方法

public void test(){
Integer i;
try{
   i = 9;
} catch (Exception ex){
   //nothing
}
int something = 1; //Breakpoint here
}
当我停在断点时,我根本看不到堆栈上的变量“I”,即使一步一步地走,我看到try块中分配了9

public void test(){
Integer i = null;
try{
   i = 9;
} catch (Exception ex){
   //nothing
}
int something = 1; //Breakpoint here
}
将变量“i”初始化为null,当到达断点时,我将看到i=9

我只是想知道引擎盖下发生了什么。编译器在第一种情况下是否没有将i放在堆栈上,或者原因是否来自JVM行为本身。

我假设您的问题中的“我根本没有在堆栈上看到变量”i“意味着您在调试器的堆栈框架中看不到它。(与JVM操作数堆栈相反,JVM操作数堆栈是字节码级别的概念。它也不在操作数堆栈上,但原因不同。)

下面是方法的
javap
(反汇编Java.class文件)输出:

  public void test();
descriptor: ()V
flags: ACC_PUBLIC
Code:
  stack=1, locals=3, args_size=1
     0: bipush        9
     2: invokestatic  #8                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     5: astore_1
     6: goto          10
     9: astore_2
    10: iconst_1
    11: istore_2
    12: return
  Exception table:
     from    to  target type
         0     6     9   Class java/lang/Exception
  LineNumberTable:
    line 27: 0
    line 30: 6
    line 28: 9
    line 31: 10
    line 32: 12
  LocalVariableTable:
    Start  Length  Slot  Name   Signature
       10       0     2    ex   Ljava/lang/Exception;
        0      13     0  this   LExample;
        6       3     1     i   Ljava/lang/Integer;
       12       1     2 something   I
在注释行(我的源文件中的第31行)上设置断点时,就是在字节码索引10处设置断点(基于
LineNumberTable
)。
LocalVariableTable
只显示从索引6到9的
i
活动,因此调试器不显示它。注意,
i
的存储位置,局部变量插槽1,在方法中没有被覆盖;即使变量不再有效,一些调试器也会利用这一点来显示值。(如果使用字节码优化器/模糊器/打包器等,它可能会更改字节码以重用局部变量槽,从而使字节码更小、更难调试或更可压缩。当然,它可能会同时完全删除调试信息。)