IntelliJ IDEA 2020系列(一)【必须GET的常用调试技巧-基础篇】

欲善其事,必利其器

一、 写在前面

1.1 什么是断点

断点(英语:Breakpoint)是程序中为了调试而故意停止或者暂停的地方。

调试设置断点可以让程序运行到该行程序时停住,借此观察程序到断点位置时,其变量、寄存器、I/O等相关的变量内容,有助于深入了解程序运作的机制,发现、排除程序错误的根源。

IDEA中一旦设置,断点将保留在项目中,直到被移除。断点只能在可执行的代码行上设置,注释、字段或方法的声明以及空行都不是断点的有效位置。

1.2 为什么要学断点调试

  • 调试是一个程序员最最最基础的技能。
  • 调试的时间也许比你编码的时间还要多。
  • 调试技能重要性甚⾄超过学习⼀门语⾔。
  • 不会调试的程序员,肯定不是一个合格的程序员。

本文主要发力讲述IDEA调试的相关技能技巧,希望对你能有所帮助。

二、断点的类型

我发现大部分的小伙伴只会用代码行左边鼠标单击这种最基础的方式打断点(即行断点)。

划重点: 调试IDEA给我们提供了丰富的断点类型,让我们能够在不同的调试场景下,使用不同的断点类型来大大提高我们的调试效率。

首先先了解下断点对话框,先有个直观的印象,你可以通过快捷键ctrl+shift+F8或菜单run-view breakpoints查看,也可以参见三、按钮介绍的S-5内容。里面涉及到的内容后面会详细讲解。
断点对话框

2.1 行断点

我们最常用的,在每一行前面点一下,出现一个小圆点,这个就是行断点。这些断点被分配到源代码行,并用于针对特定的部分进行调试。
在这里插入图片描述
临时行断点
创建方法同上,和上面的唯一区别是:把Remove once hit这个复选框给勾选上(此类型断点其实使用较少)。
在这里插入图片描述
这些断点被分配到源代码行,并用于针对特定的部分进行调试。命中时,这些断点将立即被移除。
应用场景举例
太多了,不说了

2.2 字段断点

可以设置在字段上,这样读写字段都可以触发。需要注意的是,默认只有写才会停下,想要让读取时也停下,需要右击断点,在Watch的Field access上打勾才行。
在这里插入图片描述
应用场景举例
如果在一个复杂的过程结束时,您的某个字段的结果显然是错误的值,那么设置字段点可能是确定故障来源的最快方法。

2.3 方法断点

打断点方式同上,只是它是必须把断点打在方法那一行上。方法断点可以按照方法级别跟踪程序流以及检查输入和退出条件。
它有三个特定的参数
在这里插入图片描述

  • Watch:
    • “Method entry”:进入方法时激活断点
    • “Method exit”:出去方法时激活断点
    • “Emulated”:没修改过,以下是官方的解释。

When this option is enabled, IntelliJ IDEA sets a combination of line breakpoints at the first and last statements of a method instead of using a slower “true” method breakpoint. Emulated method breakpoints improve debugging performance and thus are used by default.
We only recommend disabling this option if you are debugging remote code, or if you need to set a breakpoint at native methods or classes without line number information.

翻译如下:

启用此选项后,IntelliJ IDEA会在方法的第一行和最后一行语句中设置行断点,而不是使用速度比较慢的“ true”方法断点。 仿真方法断点可提高调试性能,因此默认情况下使用。
仅在调试远程代码或在没有行号信息的native方法或类中设置断点时,才建议禁用此选项。

应用场举例
如果你看到代码调用了一个接口,但不知道具体会跑在哪个实现上,便可以在接口上设置断点,这样不管哪个子类运行到这个方法都会停下来。

2.4 异常断点

比较小众,用过的人应该不多。
可以在Java Exception Breakpoints里添加异常的具体类型。这样的话,程序中一旦发生了这种异常马上就会停下来。默认会检索自定义的异常,会优先展示自定义的异常。
在这里插入图片描述
在代码中是看不到的,当捕捉到该异常断点的时候就会停留在异常断点处。在这里插入图片描述

应用场举例
有时候程序会抛出异常,我们需要找到为什么会抛出,什么样的条件会停留异常代码处。

2.5 断点类型小结

官方介绍中有如上四种断点,具体的断点状态和图标形状如下所示
在这里插入图片描述
重点说下三种不太好理解的状态

  • Muted
    断点被临时设置为无效状态,可以通过点击按钮mute breakpoints实现。典型的应用场景是打了很多断点,执行到中间某个断点的时候,想从新再来,又不想把后面的断点一个个点击取消,这个状态代表让后面的断点全部失效,一下执行到底。
  • Incactive/dependent
    没太理解,也没遇到过,下面是官方文档说明,待明确后补充

A breakpoint is marked as inactive/dependent when it is configured to be disabled until another breakpoint is hit, and this has not happened yet.

  • Non-suspending
    按shift+鼠标单击,可以直接设置为这种状态,理解为不被挂起,输出的信息会包含一部分的源码信息,有的人还将这个称之为源码断点
    在这里插入图片描述

三、 按钮介绍

在这里插入图片描述
H-横 S-竖
H-1:Show Execution Point (Alt + F10):如果你的光标在其它行或其它页面,点击按钮可跳转到当前代码执行行。
H-2:Step Over (F8):单步跳过,一行一行地往下走,如果这一行上有方法不会进入方法。
H-3:Step Into (F7):单步进入,如果当前行有方法,可以进入自定义的方法内部,不会进入官方类库的方法。
H-4:Force Step Into (Alt + Shift + F7):强制步入,能进入任何方法,包括官方类库,查看底层源码的时候可以用这个进入官方类库的方法。
H-5:Step Out (Shift + F8):步出,从步入的方法内退出到方法调用处,此时方法已执行完毕。
H-6: Drop Frame (默认无):回退断点,返回这个方法的调用处,这个方法重新执行,上下文也会回退。
H-7: Run to Cursor (Alt + F9):运行到光标处,你可以将光标定位到你需要查看的那一行,然后使用这个功能,代码会运行至光标行,而不需要打断点。
H-8:Evaluate Expression (Alt + F8):计算表达式,4.6章节详细说明。
在这里插入图片描述
S-1:Rerun ‘xxxx’:重新运行程序,会关闭服务后重新启动程序。
S-2:Resume Program (F9):恢复程序,比如,你在第2行和5行有两个断点,当前运行至第2行,按F9,则运行到下一个断点(即第5行),再按F9,则运行完整个流程,因为后面已经没有断点了。
S-3:Pause Program:暂停程序,启用Debug,目前没用过。
S-4:Stop ‘xxx’ (Ctrl + F2):连续按两下,关闭程序。有时候你会发现关闭服务再启动时,报端口被占用,这是因为没完全关闭服务的原因,你就需要查杀JVM进程了。
S-5:View Breakpoints (Ctrl + Shift + F8):查看所有断点。
S-6:Mute Breakpoints:静默断点,选择这个后,所有断点变为灰色,断点失效,按F9则可以直接运行完程序。再次点击,断点变为红色,有效。如果只想使某一个断点失效,可以在断点上右键取消Enabled。

四、 几个常用的调试技巧

4.1 条件断点

通过设置断点条件,至于当满足条件时,才停在断点处,否则直接运行。
举个例子,下面是个最最常见的代码,循环1000次打印一下当前的值
在这里插入图片描述
现在我们想在i== 15的时候停留下来看一下执行逻辑,该怎么操作呢,相信很多同学会在第15行打一个断点,然后运行debug,一直继续S-2(Resume Program)按钮,点击14次,直到达到i ==15。但是如果是想查看i ==800时候的逻辑,我们不可能点击800次,这时候条件断点就显得很重要了。

如图所示,右击行断点的那个小圆圈,设置一个条件i== 800,然后运行,程序就会在i==800的时候停下来。如下图所示。这个就是条件断点。
灵活使用是判断一个人调试经验很重要的依据,经常走读代码,一般会使用条件断点的同学技术能力都不会差。
在这里插入图片描述

4.2 回到上一步

行话叫断点回退,顾名思义,就是回退到上一个断点处,在多个断点的时候点击H-6回退到上个断点位置。
举个例子,如下。
在这里插入图片描述
断点回退和H-5(步出)的区别是,步出会执行完这个方法,而断点回退会直接退出这个方法。
这个在代码调试中也会非常常用,而很多的同学在调试的这种情况会重新的运行一遍代码,费时费力。

4.3 多线程调试

先来看个例子
在这里插入图片描述
IDEA的debug默认的阻塞级别是ALL,会阻塞其它线程,只有在当前调试线程走完时才会走其它线程。可以在View Breakpoints里选择Thread,如图7.1,然后点击Make Default设置为默认选项。
如下所示
在这里插入图片描述
这是再执行多线程任务就可以相互不影响,各线程依次输出了。
在这里插入图片描述也可以切换线程,在Frames的下拉列表里,可以切换当前的线程,执行代码。
在这里插入图片描述

4.4 中断调试

所谓中断调试,就是在Debug的时候,中断流程,不再走剩余的流程(比如后面的流程要删除数据库数据)了。
很多同学应该都是直接关闭重新调试程序,我之前也经常这么干。
而如果你点击停止按钮,发现后面的程序还是执行了,如下所示,明明在第8行终止了程序,你还是挂了。
在这里插入图片描述
这种情况我们可以使用中断调试,右击正在执行的断点击force return,如下所示,则小明成功的活了下来。
在这里插入图片描述

4.5 变量查看

  1. 参数所在行后面会显示当前变量的值
    在这里插入图片描述
  2. 光标悬停在参数上两秒钟,则显示当前变量信息,这种方式最快捷,用的也最多
    在这里插入图片描述
  3. 在Variables里查看,这里显示当前方法里的所有变量
    在这里插入图片描述
  4. 在Watches里,点击New Watch,输入需要查看的变量。或者可以从Variables里拖到Watche里查看。这种操作在变量层级比较深的时候会非常有用。
    在这里插入图片描述

4.6 计算表达式

在第三章中介绍的H-8 计算表达式按钮,Evaluate Expression (Alt + F8) 。可以使用这个操作在调试过程中计算某个表达式的值,而不用再去打印信息。
如下,很多时候我们想看一下23行的值,一般会在23行之前或者之后打日志查看,这样比较麻烦。此时就可以使用计算表达式。在这里插入图片描述
5. 读取变量
在这里插入图片描述
6. 计算表达式的强大之处在于不仅可以读取变量还可以设置变量
在这里插入图片描述
你会发现username.isEmpty()为true,进入到24行并执行了。

五、附录(主要参考链接)

  1. 不做 BUG 仔,必须 GET 的 IDEA 调试技巧.
  2. 官方文档.
  3. 在Intellij IDEA中使用Debug.

写在最后
关于IDEA的调试其实还有很多,比如远程调试/内存泄漏/调试lembda流等这些会在后续的IntelliJ IDEA 2020系列(二)必须GET的常用调试技巧-高级篇中介绍。

©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页