为什么我不能在 line 上放置断点String a;
?
public void localMethod() {
String a;
a = "haha";
System.out.println(a);
}
我知道局部变量在我明确地为其赋值之前不会被初始化。但它是一行代码,它做了一些事情。为什么我不能停在那里?哪些行有资格成为断点?
我正在使用 Eclipse,jdk6_31
为什么我不能在 line 上放置断点String a;
?
public void localMethod() {
String a;
a = "haha";
System.out.println(a);
}
我知道局部变量在我明确地为其赋值之前不会被初始化。但它是一行代码,它做了一些事情。为什么我不能停在那里?哪些行有资格成为断点?
我正在使用 Eclipse,jdk6_31
声明本身并不是真正的可执行代码——它只是声明某些东西的存在。您应该能够在第二行放置一个断点,这实际上做了一些事情。
诚然,我看不出 IDE 不支持将断点添加到不可执行行的概念的任何原因——它可能必须真正将断点安装在执行环境中的可执行点...
编辑:为了澄清我的意思,这段代码:
public void foo() {
String a;
String b;
a = "hello";
b = " world";
System.out.println(a + b);
}
将编译为与以下相同的字节码:
public void foo() {
String a;
a = "hello";
String b;
b = " world";
System.out.println(a + b);
}
由于声明,没有代码必须执行 - 它不会在那个时间点或类似的地方保留空间。编译器在方法的堆栈空间内分配一个“槽”,并将在整个方法中使用该槽——但它可以重用同一个槽而无需额外初始化,例如,即使变量是在循环中声明的。
断点由 IDE/编译器生成,用于监视正在执行的某些行。这些由字节码中的行号表示。表示变量声明和初始化的字节码在编译过程中合并为一个步骤。因此,如果从赋值中分离出变量的声明,则生成的字节码中没有可用的断点。
这是您的示例的字节码:
public class Example {
public void localMethod() {
String a;
a = "haha";
System.out.println(a);
}
}
到:
public class stackoverflow/Example {
// compiled from: Example.java
// access flags 0x1
public <init>()V
L0
LINENUMBER 6 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this Lstackoverflow/Example; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x1
public localMethod()V
L0
LINENUMBER 9 L0
LDC "haha"
ASTORE 1
L1
LINENUMBER 10 L1
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ALOAD 1
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
L2
LINENUMBER 11 L2
RETURN
L3
LOCALVARIABLE this Lstackoverflow/Example; L0 L3 0
LOCALVARIABLE a Ljava/lang/String; L1 L3 1
MAXSTACK = 2
MAXLOCALS = 2
}
请注意,第 8 行没有 LINENUMBER 标记,在我的 IDE 中它代表String a
声明。
没有对应于a
局部变量声明的字节码,因此您不能在声明时设置断点,只能在初始化时设置。
示例.java:
class Sample {
public void localMethod() {
String a;
a = "haha";
System.out.println(a);
}
}
javac 示例.java; javap -c 示例
class Sample extends java.lang.Object{
Sample();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public void localMethod();
Code:
0: ldc #2; //String haha
2: astore_1
3: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
6: aload_1
7: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
10: return
}
断点允许用户在特定位置暂停程序的执行。断点通常与源代码一起显示在 UI 中。当程序执行过程中遇到断点时,程序会挂起并触发以 BREAKPOINT 为原因的 SUSPEND 调试事件。现在..当你编译它时..声明和赋值属于一个步骤..首先它被声明然后赋值..所以最后一步是赋值..因此,你可以在赋值上放一个断点,但不能关于申报。