IDEA调试技巧

2023-11-05

 在项目开发的时候很多小伙伴能非常熟练的使用IDEA编写代码,但是对于IDEA调试的技巧掌握的不是很好,只会F7、F8、F9等这些基本调试功能。

而像一些复杂的调试场景就无从下手,如:在for循环中调试某个特定值;修改变量的运行值等。

本文介绍了idea的bug调试基本操作及高级技巧,看完掌握后调试bug的效率一定大大提升。


一、概述

  • debug调试也叫断点调试
  • Debug用来追踪代码的运行流程,通常在程序运行过程中出现异常,启用Debug模式可以分析定位异常发生的位置,以及在运行过程中参数的变化。
  • 在程序的某一行打上断点,则在debug模式下运行到断点位置时会暂停,便于程序员观察代码的执行情况
  • 通常我们也可以启用Debug模式来跟踪代码的运行流程去学习三方框架的源码。
  • 学会debug,有助于在程序运行未达到理想情况时,对程序的各个流程进行分析
  • 本文详细描述了 IntelliJ IDEA 的debug的一些基本的常用操作和 IntelliJ IDEA 高级调试技巧

二、debug基本操作

2.1、打断点

在程序的某一行位置,数字右边的空白部分使用鼠标左键点击一下,出现红点即为打上了一个断点

2.2、运行debug模式

方式一

选中要进行debug的程序,点击右上角的debug按钮(快捷键:Shift+F9)

方式二

在要进行debug的程序处右键,选中下图选项

2.3、重新执行debug

点击下图按钮(快捷键:Ctrl+F5),会关闭当前debug的程序并重新启动debug

2.4、让程序执行到下一次断点后暂停

点击下图的按钮(快捷键 :F9),debug会继续运行程序,直到遇到下一次断点后暂停

举例

下图是一个循环操作,在打断点的位置点击上面说的按钮,相当于再循环一次,到代码第14行时停止

2.5、停止debug程序

点击下图按钮(快捷键:Ctrl+F2)停止debug程序

注意

运行的如果是javaSE项目,点一下就停止

运行的如果是javaWeb项目,需要点两下

第一下停止代码的当前线程

第二下停止服务器

2.6、显示所有断点

点击下图按钮(快捷键:Ctrl+Shift+F8),会显示所有断点

2.7、添加断点运行的条件

选中断点,右键后即可编辑断点运行的条件

满足条件时程序才会在该断点处停下

比如添加i==4,重新debug后的效果如下图所示

2.8、屏蔽所有断点

点击下图按钮,可以屏蔽所有断点

屏蔽前

屏蔽后

屏蔽的断点在debug的时候不会运行

如果程序调试后觉得没问题了,可以屏蔽掉所有断点继续运行程序查看效果

2.9、把光标移到当前程序运行位置

点击下图按钮(快捷键:Alt + F10 )后,会把鼠标光标移动到当前程序运行位置

当程序代码量很大的时候,可以通过该按钮快速定位到程序运行位置

如下图所示

假设程序运行到第14行断点处,鼠标光标在第3行,点击该按钮后光标就会移动到第14行

2.10、单步跳过

点击下图(快捷键:F8 )按钮,会一行一行执行自己编写的代码

如果碰到方法,该按钮不会进入到该方法内部

2.11、可以跳入方法内部的执行一行代码操作

下图中的蓝色箭头(快捷键:F7)和红色箭头(快捷键:Alt+Shift+F7)都可以执行一行代码,如果遇到方法时会进入方法内部,区别在于

蓝色箭头(快捷键F7)只会跳进自己写的方法,如果是系统已经写好的方法,蓝色箭头无法跳入该方法

红色箭头(快捷键Alt+Shift+F7)不管是自己写的方法,还是系统已经定义好的方法,都可以跳入方法内部

如下图所示

Random的方法是系统已经写好的,蓝色箭头无法跳入方法内部,但是红色箭头可以跳入方法内部

isEvenNumbers()是自定义方法,红色和蓝色箭头都可以跳入该方法内部

2.12、跳出方法

下图的两个按钮

(快捷键:Shift+F8)和 都可以跳出方法

第二个按钮是关闭窗口的意思,同样可以起到跳出方法的作用

在进入方法内部的时候使用这两个按钮

2.13、直接执行到光标所在位置

点击下图的按钮(快捷键:Alt+F9),程序会执行到光标所在的位置

前提是光标前面没有断点,否则程序还是会在光标前面的断点处暂停

2.14、变量查看

2.14.1.在IDEA中,参数所在行后面会显示当前变量的值

2.14.2.光标悬停到参数上,显示当前变量信息

2.14.3.在Variables里查看,这里显示当前方法里的所有变量

2.14.4.在Watches里,点击New Watch,输入需要查看的变量。或者可以从Variables里拖到Watche里查看

如果你发现你没有Watches,点击重置布局


三、debug高级技巧

3.1、断点处添加 log

很多程序员在调试代码时都喜欢 print 一些内容,这样看起来更直观,print 完之后又很容易忘记删除掉这些没用的内容,最终将代码提交到 remote,code review 时又不得不删减这些内容重新提交,不但增加不必要的工作量,还让 log tree 的一些节点没有任何价值。

IntelliJ IDEA 提供 Evaluate and Log at Breakpoints 功能恰巧可以帮助我们解决这个问题, 来看下面代码:

/**
 * @author daisl
 * @date 2022/4/12
 */
public class Test {
    public static void main(String[] args) {
        Random random = new Random();
        int count = 0;
        for (int i = 0; i < 5; i++) {
            if (isEvenNumbers(random.nextInt(10))) {
                count++;
            }
        }
        System.out.printf("Found %d isEvenNumbers values%n", count);
    }

    private static boolean isEvenNumbers(int i) {
        return i % 2 == 0;
    }
}

假如我们想在第 18 行查看每次调用,随即出来的 i 的值到底是多少,我们没必要在这个地方添加任何 log,在正常加断点的地方使用快捷键 Ctrl+Shift + F8,就会弹出下面的内容

勾选上 Evaluate and log, 并自定义你想查看的 log/变量,比如这里的 "isEvenNumbers=" + i, 这样以 Debug 模式运行程序(正常模式运行,不会打印这些 log):

如果你在多处添加了这种断点,简单的看 log 可能偶尔还是不够直观,可以勾选上面图片绿色框线的 "Breakpoint hit" message :

如果你想要更详细的信息,那就勾选上 Stack trace (大家自己查看运行结果吧),有了这个功能,上面说的一些问题都不复存在了

3.2、断点处添加条件

循环中经常用到这个技巧,比如:遍历1个大List的过程中,想让断点停在某个特定值。

参考上图,在断点的位置,右击断点旁边的小红点,会出来一个界面,在Condition这里填入断点条件即可,这样调试时,就会自动停在i=4的位置

3.2、字段断点

如果你阅读源码,你一定会有个困扰,类中的某个字段的值到底是在哪里改变的,你要一点点追踪调用栈,逐步排查,稍不留神,就可能有遗漏

我们可以在 IntelliJ IDEA 中为某个字段添加断点,当字段值有修改时,自动跳到相应方法位置

具体方法:

  1. 在字段定义处鼠标左键添加断点(会出现「眼睛」的图标)

  1. 在「眼睛」图标上鼠标右键
  2. 在弹框中勾选上 Field access 和 Field modification 两个选项

3.3、异常断点

除了阅读源码,一定是遇到了异常我们才开始调试代码,代码在抛出异常之后会自动停止,但是我们希望:

代码停在抛出异常之前,方便我们查看当时的变量信息

这时我们就用到了 Exception Breakpoints, 当抛出异常时,在 catch 的地方打上断点,可以通过下图的几个位置获取栈顶异常类型,比如这里的 NullPointerException

知道异常类型后,就可以按照如下步骤添加异常断点了:

然后在弹框中选择 NullPointerException

重新以 Debug 模式运行程序:

程序直接定位到抛出异常的位置

3.4、智能步入

一行代码里有好几个方法,怎么只选择某一个方法进入。使用Step Into (Alt + F7) 或者 Force Step Into (Alt + Shift + F7) 进入到方法内部,但这两个操作会根据方法调用顺序依次进入,这比较麻烦。

那么智能步入就很方便了,智能步入,这个功能在Run里可以看到,Smart Step Into (Shift + F7)

Shift + F7自动定位到当前断点行,并列出需要进入的方法,点击方法进入方法内部。
如果只有一个方法,则直接进入,类似Force Step Into(Alt + Shift + F7)

3.5、断点处再加一行代码

点击下图的加号,可以在断点处加一行代码,比如下图中的i++即为新添加的代码

选中i++,右键点击Edit可以编辑该代码

选中该行代码(i++),点击加号下面的减号,可以删除该行代码

选中下图的眼镜,变为分屏操作

3.6、在控制台改变正在debug的数据

在控制台选中某个变量,右键点击Set Value可以改变该变量的值

如果想测试某个地方的数据如果是正确的会是什么效果,可以手动更改该处变量的值

3.7、中断Debug

想要在Debug的时候,中断请求,不要再走剩余的流程了?

有些时候,我们看到传入的参数有误后,不想走后面的流程了,怎么中断这次请求呢(后面的流程要删除数据库数据呢….),难道要关闭服务重新启动程序?嗯,我以前也是这么干的。

确切的说,我也没发现可以直接中断请求的方式(除了关闭服务),但可以通过Force Return,即强制返回方法返回值来避免后续的流程

点击Force Return,弹出Return Value的窗口,我这个方法的返回类型为boolean,所以,我这里设置当前方法返回false,来强制返回,从而不再走方法后面代码。

3.8、多线程调试

当有多个线程时,我们如何控制线程的执行顺序呢?
代码如下:

/**
 * @author daisl
 * @date 2022/4/13
 */
public class Test1 {
    public static void main(String[] args) {
        System.out.println("主线程开始");
        new Thread(() -> {
            System.out.println("我是线程1-1");
            System.out.println("我是线程1-2");
            System.out.println("我是线程1-3");
        }, "线程1").start();

        new Thread(() -> {
            System.out.println("我是线程2-1");
            System.out.println("我是线程2-2");
            System.out.println("我是线程2-3");
        }, "线程2").start();

        System.out.println("主线程开始结束");
    }
}

普通模式debug模式下是做不到的,因为我们没办法控制线程的执行顺序。需要做如下设置

  1. 鼠标左键在行数上加上断点

2.鼠标右键打开断点配置,选中Thread选项后,点击 mark default(有就设置),然后点击 Done保存

设置后的断点如下,3个断点都是Thread模式

3.启动项目,控制指定线程输出内容

执行到某个语句想切换线程的时候选中下拉框中下一步要执行的线程即可

  • Frames的下拉列表里,可以切换当前的线程,如下我这里有两个Debug的线程,切换另外一个则进入另一个Debug的线程

3.9、回到"上一步"

该技巧最适合特别复杂的方法套方法的场景,好不容易跑起来,一不小心手一抖,断点过去了,想回过头看看刚才的变量值,如果不知道该技巧,只能再跑一遍。

此时我们的断点已经到isEvenNumbers方法了,如何回到上一个method方法中呢?

点击

Drop Frame,即可回退到上一个方法。

断点回退只是重新走一下流程,之前的某些参数/数据的状态已经改变了的是无法回退到之前的状态的,如对象、集合、更新了数据库数据等等。

3.10、方法断点

方法断点是三角形的断点,主要的作用是,点击F9,

3.10.1进入到方法中第一行和最后的一行

3.10.2在接口上打断点,当一个接口有多个实现类,在接口的方法上打断点,可以快速的定位到具体的实现类上

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

IDEA调试技巧 的相关文章

随机推荐

  • 【手把手教你】使用pyfinance进行证券收益分析

    pyfinance简介 在查找如何使用Python实现滚动回归时 发现一个很有用的量化金融包 pyfinance 顾名思义 pyfinance是为投资管理和证券收益分析而构建的Python分析包 主要是对面向定量金融的现有包进行补充 如py
  • 汇编语言与微机原理(1)基础知识

    前言 1 本人使用的是 王爽老师的汇编语言第四版和 学校发的微机原理教材配合学习 2 推荐视频教程 通俗易懂的汇编语言 王爽老师的书 贺老师C站账号网址 3 文章配套资料 Github仓库链接 4 本文是介绍8086汇编语言 汇编语言简介
  • 基于51单片机的心率计脉搏体温测量仪WIFI传输APP设计方案原理图

    系统的功能分析及体系结构设计 末尾附文件 系统功能分析 本系统采用STC89C52单片机 LCD1602液晶 脉搏传感器 温度传感器DS18b20 WIFI模块电路设计而成 1 LCD1602液晶第一行显示设计信息 第二行显示心率和温度 2
  • 嵌入式软件开发之程序分层(二)

    前言 该内容是工作一年来通过上网或其他方式不断搜索 实践 总结出来的嵌入式软件开发经验 本文仅适用于单片机的裸机开发 希望能帮到正在学习这方面的朋友 如有不好的地方 请多多见谅 在嵌入式软件开发过程中 在程序架构的搭建完成之后 为了提高项目
  • 深度学习速成(5)torch.nn.Module类

    nn Module 是PyTorch中的一个基础类 nn即是Neural Networks 用于构建神经网络模型 所有的神经网络模型都必须继承于nn Module类 并实现 forward 方法来定义模型的前向传播过程 nn Module类
  • nginx 配置静态网页

    nginx 配置静态网页 进入配置文件 etc nginx conf d default conf 配置的时候小伙伴们一定要记得先备份一份文件 这样方便后续出错恢复 server listen 端口号 server name IP loca
  • 解决Springboot GET请求参数过长的情况

    项目场景 使用Spring Boot进行项目开发 解决Springboot GET请求参数过长的情况 问题描述 报错信息 Springboot GET请求参数过长抛出异常 Request header is too large 的问题 现象
  • 华为OD机试 - 冠亚军排名,奖牌榜排名(Java)

    题目描述 2012伦敦奥运会即将到来 大家都非常关注奖牌榜的情况 现在我们假设奖牌榜的排名规则如下 首先gold medal数量多的排在前面 其次silver medal数量多的排在前面 然后bronze medal数量多的排在前面 若以上
  • 2022-12-27 使用lodash库实现两个非空对象的深拷贝并输出这两个对象的并集

    问题描述 遇到这样一个题 如下 const a fruits apple banana series apple C banana A B const b fruits banana orange animals pig series ba
  • ESP32S系列芯片通过EC20完成OTA统一流程

    uint32 t end size 0 最后一包的大小 uint16 t page number 0 总包数 uint16 t now number 0 当前写入页数 uint32 t bin addr 0 文件地址指针偏移量 uint16
  • DSMM数据安全概述

    数据安全生命周期分为采集 传输 存储 处理 交换 销毁几个阶段 其中数据处理阶段是整个周期的核心阶段 数据处理安全与否直接关系到整体数据安全 那么今天分享内容就是数据处理安全的相关要求和实现目标 DSMM是Data Security cap
  • URP学习--LitShader

    我们来看一下URP下的LitShader LitShader也是基于物理渲染的 很多方法和属性看过默认管线PBR代码的应该都会很熟悉 我们现在再过一遍 加深一下印象 同时疏通一下以前可能没有掌握的地方 先看Shader的Properties
  • mysql workbench 建库建表

    选择Create Schema建库 选择Create Table建表 改表名 上拉箭头选择更多 此处最好全屏 不然显示不全
  • UE5实现物体高亮描边效果(含UE相关源码浅析)

    文章目录 1 实现目标 2 实现过程 2 1 UE Editor中相关源码 2 2 深度值描边 2 3 半透明材质处理 2 4 遮挡处理 2 5 视口边缘处理 3 参考资料 1 实现目标 在UE5中实现物体边缘高亮效果 且在被遮挡时在边缘显
  • Android报Caused by: android.content.res.Resources$NotFoundException: String resource ID #0x0 .解决办法

    如果遇到这个问题 首先考虑以下原因 你是否在setText 方法中设置了一个int型变量 比如setText 10 这样Android系统就会主动去资源文件当中寻找 但是它不是一个资源文件ID 所以就会报出这个bug 解决办法 将int型业
  • 多维时序

    多维时序 MATLAB实现LSTM长短期记忆神经网络多变量时间序列预测 考虑历史特征的影响 多指标 多图输出 目录 多维时序 MATLAB实现LSTM长短期记忆神经网络多变量时间序列预测 考虑历史特征的影响 多指标 多图输出 效果一览 基本
  • linux - 文件利用率快满了 - mongo日志

    https zhuanlan zhihu com p 82430795 查看文件利用率 df h 文件夹大小 ls lh 逐级搜索大文件或目录 du sh cd 返回上一层 ps ef grep mongo 启动 mongodb bin m
  • 布尔值(python)

    while语句 格式 while 表达式 语句 逻辑 当程序执行到while语句时 首先计算表达式的值 如果表达式的值为假 那么结束整个while语句 如果为真 则先执行语句 再去计算表达式的值 如果表达式的值为假 那么结束整个while语
  • 从匿名函数到函数式编程

    什么是匿名函数 匿名函数是一种没有名称的函数 也被称为 lambda 函数或者函数字面量 和普通函数不同 匿名函数不需要在定义时指定函数名 通常是在需要的时候直接定义和使用 匿名函数通常被用作一次性的函数 例如作为其他函数的参数或者返回值
  • IDEA调试技巧

    在项目开发的时候很多小伙伴能非常熟练的使用IDEA编写代码 但是对于IDEA调试的技巧掌握的不是很好 只会F7 F8 F9等这些基本调试功能 而像一些复杂的调试场景就无从下手 如 在for循环中调试某个特定值 修改变量的运行值等 本文介绍了