一文带你掌握idea的调试功能
一文带你掌握idea的调试功能_idea接口调试-CSDN博客
背景
相信正儿八经的程序员应该没有从没搞过软件调试的,当我们发现程序的有些行为不符合自己预期时,经常需要通过调试来定位问题,但是我相信绝大多数人可能还是低估了调试的重要性,下面说一下我的个人经历。
最近我们公司的项目因为迁移了环境,导致项目在本地启动不了,只能在测试环境启动,结果就是我们排查问题只能通过看日志解决,结果导致我排查问题的效率大大降低,因为我需要在很多地方添加日志打印,了解一些关键变量的值,接下来我还要重新打包部署,然后再到测试环境复现问题,将日志下载到本地,整个过程相当花时间,如果某个地方自己忘记打印日志了,上面的过程还得重新再来一遍,非常浪费时间,通常一上午过去了,却没解决几个问题。不仅仅定位问题变得更加困难,连修复问题都变得更困难了,因为我在改了代码后,本地跑不起来,就只能部署到测试环境,然后复现问题,看看问题是否得到了解决。如果还是有问题,自己还得重新打包部署,重新复现问题…修复问题的效率也变得极低,整个过程繁琐的让人沮丧。
在项目迁移环境前,我们基本上都是通过本地调试来排查问题的,根本不需要做打印日志、打包、部署、下载日志的事情,我们可以通过接口测试 + 调试快速定位到问题,然后修改代码,本地自测,定位问题和解决问题的速度非常快。
总而言之,最近的经历让我意识到了调试的重要性。过去我也只是了解一些基本的调试功能,而现在我觉得有必要更加系统的掌握各种调试技巧,这将对自己排查问题很有帮助。
目前绝大部分公司的java项目都是使用idea软件开发的,所以接下来我将带大家一起研究idea的各种调试技巧。
普通断点
首先如果我们想要使用idea调试代码,就需要以调试的模式启动项目,点击这个虫子按钮即可
idea调试中最重要的就是打断点,断点就是我们希望程序在哪个地方停下来,然后我们就可以看到当程序走到断点处时,前面各个变量的值是多少,比如下图中我们可以看到用户请求参数中的id的值为1
条件断点
上面是普通断点,用来告诉idea当程序走到这个断点处时停下来。下面我们来看看另一种更强大的断点,通常我们管它叫条件断点,条件断点通常长这个样子(见下图),相当于在普通断点的基础上增加了一个?
当我们在普通断点处右键单击后会出现下图所示的弹框,然后我们在condition这一行中输入条件,表示只有程序满足这个条件表达式时才会在断点处停下,否则继续执行。
条件断点最大的好处就是可以提升调试代码的效率,比如一个集合中有10000个元素,而我们只想看到第99个元素的处理过程,如果不使用条件断点,我们需要点击下面这个按钮98次,这还不把人折磨的要疯掉。而使用条件断点,我们只需要输入i == 99即可让程序只在处理第99个元素时停下来。
另外在条件断点的表达式中还支持方法调用,跟我们平时写代码差不多,这个功能非常好用。我在工作中经常会用条件断点了解程序的处理流程。
常用的断点调试按钮
下面是常用的断点调试按钮,我们可以通过这些按钮控制程序继续往下走或者进入某个具体的方法,或者直接走到下一个断点等等。
比如我想查看userService.getUser(id)这个方法的具体处理逻辑,就可以点击下面这个按钮实现:
可以看到现在程序确实进到了getUser方法中
我们还可以通过下图中的按钮快速回到程序所处的断点处,这在我们看代码时非常有用:
下图中按钮的作用设置临时断点,比如程序现在停留在前面的某个断点,我可以点击这个按钮让程序快速执行到自己鼠标的光标处停下来,效果就相当于在鼠标光标处设置了一个临时断点。
下图这个按钮的作用是快速跳出当前代码块,比如我这里的断点在for循环中,当我点击这个按钮后,程序就在这个for循环外停下了。
另外idea还有一个功能非常惊人,相当于让时光倒流。点击这个按钮相当于让代码从下往上走,相当于回到过去,回到调用当前方法前的那个方法,reset frame相当于回退到栈的上一个状态,也就是上一个方法,因为方法的执行是依赖栈实现的。
点击下图的这个按钮可以让方法提前返回,或者用于修改方法的返回值,有点类似于mock框架的作用
另外我们还可以通过点击下面这个【evaluate expression】这个按钮来快速查看某个方法的返回结果或者某个变量的值
点击evaluate即可得到某个表达式的结果
观察特定变量的值
我们还可以将一些自己关心的变量的值添加到watches中,这样可以随时在调试的variables面板中看到这个变量的值,这样可以让变量查看变得更加方便。
被观察的变量有个眼镜,表示这个变量处于被观察的状态中,如下图所示:
我们还可以看到所有被观察的变量都放在最前面,因为这些是我们关心的变量,另外我们还可以通过下面的输入框来添加自己需要观察的变量到watches中,而且我们同样可以输入表达式,比如我这里通过users.get(0)表示我只想观察users集合中第一个对象的值。总而言之,我们可以通过add watches这个功能快速查看自己关心的特定变量的值。
远程调试
不知道有没有朋友使用过idea的远程调试,远程调试就是当我们请求测试环境(或者生产环境)的接口时,idea可以对远程应用进行断点调试。但是这样做有一个前提条件,那就是:远程应用的代码要和自己本地的代码完全一样!
下面是远程调试的具体步骤:
- 1.首先,我们需要在远程服务器上以debug的模式启动springboot应用,我这里是使用docker-compose部署的springboot项目,注意看那个环境变量,我在里面就设置了远程调试的端口号是5005
1 | services: |
我们可以看到springboot容器的日志中有下面这两句话,说明我们的springboot应用正在监听5005端口

为了安全起见,咱们远程调试最好还是使用ssh的方式连接远程服务器,否则会很容易被攻击。
我们在本机电脑的cmd窗口中执行下面的指令:
1 | # 建立本机电脑和远程服务器的ssh隧道,将远程服务器的5005端口号映射到本机的5006端口号 |
- 2.接下来就是配置idea远程调试
选择edit configuration
点击+,选择remote jvm debug
由于本地的5006端口已经映射到了远程服务器的5005端口,也就是springboot应用的调试端口,所以我们可以通过这里的配置连上远程的springboot应用
点击下图中的虫子按钮,开启远程调试
下面是开启远程调试后的样子
先在想要调试的接口中打断点
接下来,我们访问远程服务器上的该接口
接下来会发生一件很神奇的事情,请求停在了我们本地项目的断点上!
然后我们就可以像调试本地代码一样调试远程代码了,这就是远程调试
那么远程调试到底有什么用呢?什么时候会用到远程调试?
绝大部分测试环境上遇到的问题都是可以在本地复现的,然后有些时刻我们无法在本地复现测试环境的问题,这时候就需要远程调试了,我们可以通过远程调试来了解测试环境上的问题是如何产生的,这比自己添加日志打印,然后重新打包部署的方式效率要高很多,这就是远程调试的价值。
查看堆栈信息
有时候当程序走到我们的断点的时候,我们很想知道程序是怎么走到这个地方的,程序在走到这个断点之前经历了什么故事。在软件开发中,我们将这种信息叫做堆栈信息,通俗来说,就是指程序走过的路线。任何一个有经验的程序员都知道程序堆栈信息的重要性,当程序报错时,他们会第一时间查看程序的堆栈信息。那么我们在调试时该如何知道这个信息呢?
比如我想知道程序是如何走到controller的,首先我在controller的接口中打一个断点,然后可以在下图中看到程序是如何走到这个断点的。
还可以在这里直接搜索我们感兴趣的类,比如我这里搜索了dispatcherservlet,然后我们就能找到自己关心的类了。也就是说,程序在走到controller前先经过了DispatcherServlet。
我们还可以直接双击其中的某个栈(也就是堆栈列表中的某一行),可以直接跳到对应的代码,帮助我们了解程序是从这个类的哪一行代码中进入到我们的断点所在处。
这个功能非常好用,自从知道了这个技巧后,我不管是排查问题,还是阅读框架源码都变得更加轻松了,希望大家务必掌握!
需要注意的地方是:如果你看到的堆栈信息是这个样子,光秃秃的,什么都看不到。如下图所示:
这很可能是因为你将依赖jar包中的堆栈信息给过滤掉了,点击下方图中中的按钮即可显示所有的堆栈信息。
除了上面这种方式外,还有另一种方式,那就是使用我们前面提到的值表达式,也就是evaluate express,在里面输入Thread.currentThread().getStackTrace(),即可知道程序的堆栈信息(或者说是路线信息)。
通过下图,我们可以看到这种方式也能帮助我们获得程序的路线信息
还有的时候,项目因为某些原因在本地无法启动,需要在测试环境中才能运行项目。这时候我们需要了解程序的堆栈信息,也就是程序的行军路线图。此刻我们又无法使用idea的调试,那我们该怎么办呢?
其实很简单,我们直接加一行日志,打印程序执行到此处的堆栈信息即可,如下图所示:

增加的堆栈信息日志代码为:
1 | StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); |
然后我们就能在测试环境的日志中看到类似于下图中的堆栈信息了

总而言之,程序的堆栈信息就是程序员的命根子,它非常非常重要,知道了堆栈信息一切都好办。不知道堆栈信息就只能凭运气和瞎猜以及加班来定位和解决问题了。
最后的总结
今天我们将了idea的调试功能的价值在于提升我们排查问题和修复bug的效率,然后我们还讲到了idea调试的各种技巧,包括条件断点,如何通过idea的一些调试按钮调整程序的执行进度,以及查看关键变量的值等等。
最后我们还分享了idea远程调试的技术,用来定位一些本地开发环境无法复现的问题。实际上除了远程调试外,我们还有一些其他的工具来定位生产或测试环境中的问题,比如arthas,这个我们放到后面的文章中说。
觉得有收获的朋友可以点个赞,您的鼓励就是我最大的动力!