断点调试

断点调试是指在程序的某一行设置一个断点,调试时,程序运行到断点就会停住,然后可以一步步往下调试运行,调试过程中可以看到各个变量当前的值,出错的话,调试到出错的代码行即显示错误停下。此时程序员可以进行分析从而找到找个Bug

DeBug也可以帮助程序员查看java底层源代码的执行过程
重点在DeBug时,是运行状态,是以对象的运行类型来执行的。

DeBug单步执行

在IDEA集成开发环境软件中有众多快捷键来帮助程序员进行断点调试
F7:跳入
F8:单步执行 StepOver
Shift+F8:跳出
F9:执行到下一个断点(resum)

用一段代码来了解debug

public class Test01 {
    public static void main(String[] args) {
        int sum = 0;
        for (int i = 0; i < 3; i++) {
            System.out.println("i = "+i);
            sum+=i;
            System.out.println("sum = "+sum);
        }
        System.out.println("循环结束了");
    }
}

如果只是运行只能看到控制台输出运行后的语句。而无法看到是怎么输出的,debug就可以看到变量的创建和一步步变化

android stduio debug断点变量不显示 debug断点调试_数组


上面是debug时的控制界面

android stduio debug断点变量不显示 debug断点调试_System_02


F8:单步执行 StepOver

当点击这个按钮时,就会执行一步代码,例如点击一下就会生成变量sum,并赋值 0

android stduio debug断点变量不显示 debug断点调试_System_03


当在debug时,可以看下方的debug区看变量情况,也可以看源码区,也会有变量的实时情况

android stduio debug断点变量不显示 debug断点调试_数据结构_04

DeBug异常显示

debug是用于超出bug,找出异常的,下面用数组下标越界异常,来测试看看debug会怎么显示
使用F8单步执行 StepOver

public class Test01 {
    public static void main(String[] args) {
        int [] a = {1,2,3};
        for (int i = 0; i <= a.length; i++) {
            System.out.println(a[i]);
        }
    }
}

可以看到上面 数组 a的空间只有3,for循环用的是i<=a.length允许i自增到3,但是数组的下标只有0/1/2.没有3所以肯定会报下标越界异常

android stduio debug断点变量不显示 debug断点调试_jvm_05

可以看到开没有进入for循环的时候就已经提示了会有数组下标异常

继续执行i = 3 时,输出台还没有显示异常,但是debug区已经报异常了

android stduio debug断点变量不显示 debug断点调试_System_06


因此可以根据报的错误信息,进行修改

使用F7step into追源码和Shift +F8 step Out退出

当debug时,遇到使用方法,如果继续用F8 step over单步执行,就会跳转到方法执行后的样子,无法看到方法执行。
因此当debug到使用某个方法时,需要使用F7 step into,进入方法内部。如果方法里面调用的是另一个方法,也可以使用step into继续进入。当不想看方法内部时 可以使用Shift +F8 step Out,推出方法,继续执行程序的下一步。

注意:直接使用F7step into时需要配置一下 (File–Settings–BuildExecutionDeployment–Debugger–Stepping)将java和javax取消勾选,否则只能使用 Alt+Shift+F7 force step into强制进入

使用一段代码加深印象

public class Test01 {
    public static void main(String[] args) {
        int [] arr  = {-10,54,21,-1};
        Arrays.sort(arr);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+" ");
        }
    }
}

在Arrays.sort(arr);处添加断点,运行debug。

android stduio debug断点变量不显示 debug断点调试_数组_07


使用F7 进入方法 可以看到跳转到了另一个类的方法里

android stduio debug断点变量不显示 debug断点调试_java_08


由于这个方法是调用另一个了类的方法,所以可以继续F7进入

android stduio debug断点变量不显示 debug断点调试_数组_09


当不想继续看了时,使用Shift+F8退出,原路返回到程序,但是不是一步到位,而是沿途返回

【main方法–F7–A类的方法–F7–B类的方法–Shift+F8–A类的方法–Shift+F8–main方法】

返回继续执行完毕 输出排序好的数组

使用F9 Resume Program 跳转到下一个断点

案例演示

public class Test01 {
    public static void main(String[] args) {
        int [] arr  = {-10,54,21,-1};
        Arrays.sort(arr);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+" ");
        }
        System.out.println("100");
        System.out.println("200");
        System.out.println("300");
        System.out.println("400");
        System.out.println("500");
    }
}

android stduio debug断点变量不显示 debug断点调试_java_10


如图在第8行和第13行下断点,当使用debug时,首先会运行到第8行停下,我们可以使用F8一步步下去,如果不关系下面的,只想快速到某一行,就需要使用F9 Resume Program 跳转到下一个断点停下。

输出结果:

第一次断点

android stduio debug断点变量不显示 debug断点调试_System_11


使用F9

android stduio debug断点变量不显示 debug断点调试_System_12


android stduio debug断点变量不显示 debug断点调试_数据结构_13

可以看到已经将排序好的数组数组,而且100也输出了

  • F9 Resume Program 跳转到下一个断点也可以用来判断业务逻辑,例如上面的 Arrays.sort(arr),可以在别的类中方法定一个断点,看看debug会不会执行到那去,如果执行到那去就是相关的,如果还是在原来的地方运行就是没有逻辑关系

A类运行main方法,B类的某个方法中下断点

使用debug看对象创建的过程

public class Test02 {
    public static void main(String[] args) {
        Person p1 = new Person("李想",22);
        System.out.println(p1);
    }
}
class Person{
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

当断点在 Person p1 = new Person(“李想”,22);,时可以使用强制进入看看具体的创建过程

alt+shift+F7强制进入可以看到进入了class load(加载类)的loadClass类加载方法

android stduio debug断点变量不显示 debug断点调试_System_14


再使用shift+f8退出到main方法继续

android stduio debug断点变量不显示 debug断点调试_System_15


可以看到将传入的实参到构造方法赋值给对象

接着F8继续 进入到重写的toString方法,输出属性,执行完毕输出 :Person{name=‘李想’, age=22}

debug看动态绑定机制

public class Test01 {
    public static void main(String[] args) {
       A a = new B();
        System.out.println(a.sum());
    }
}
class A{
    int i = 10;
    public int sum(){
        return get()+10;
    }
    public int get(){
        return i;
    }
}
class B extends  A{
    int i = 20;
    public int sum(){
        return get()+10;
    }
    public int get(){
        return i;
    }
}

断点打在 System.out.println(a.sum());

使用强制进入看看

android stduio debug断点变量不显示 debug断点调试_数据结构_16


可以看到由于运行类型是B,所以进入的是B类的sum方法,由由于此sum方法中调用了get方法放,又会进入到B类的get方法

android stduio debug断点变量不显示 debug断点调试_数组_17