您好,我是码农飞哥,感谢您阅读本文!如果此文对您有所帮助,请毫不犹豫的一键三连吧。小伙伴们,有啥想看的,想问的,欢迎积极留言告诉我喔。 前面我写了一篇低效编码的文章,我很痛心。【低效编码】一个@ResponseBody注解没加让我这个菜鸟原形毕露 。于是我决定痛定思痛,好好反思。不能在低效编程下去了,我要支楞起来;我要高效编程;非常非常高效的编程。所以这篇文章来了,他主要讲述Idea的Debug的一些基本知识和常用技巧以及如何进行远程调试。代码调试是我们每个程序猿每天都会做的事情,是排除BUG,检查代码逻辑的一个非常有效的方法。
环境
本文所设计的软件环境如下表所示:
软件 | 版本 |
IntelliJ IDEA | 2018.3.6 x64 |
SpringBoot | 2.4.5 |
调试的那些小秘密(Debug的使用)
工欲善其事,必先利其器,要想很好的使用Idea的Debug功能,首先需要我们对其有很好的了解。
唤出Debug窗口
如果你的Idea不能展示Debug窗口,可以在Settings中进行如下设置,选中 Show debug window on breakpoint
认识IDEA的Debug窗口
上面展示了一个长相正常的Debug的窗口。我标出了八个部分,这八个部分的文字解释是:
1.第一部分:启动:以调试模式启动程序,只有以Debug的方式运行程序才会出现Debug
2.第二部分:断点:在左边行号栏单击左键,或者快捷键Ctrl+F8 打上/取消断点,断点行的颜色可自己去设置
3.第三部分:Debug窗口:访问请求到达第一个断点后,会自动激活Debug窗口。如果没有自动激活,可以去设置里设置。
4.第四部分:这一部分有七个按钮,
功能有重启程序,查看所有断点,使断点失效,具体每个按钮的作用描述如下表所示:
5.第五部分:一共八个按钮,每个按钮的作用分别是:
Show Execution Point(Alt+F10) : 如果你的光标在其他行或者其他页面,点击这个按钮可跳转到当前代码的行。
Step Over (F6):步过,一行一行地往下走,如果这一行上有方法不会进入方法。
Step Into(F7): 步入,如果当前行有方法,可以进入方法内部,一般用于进入自定义方法内,不会进入官方类库的方法
Force Step Into (Alt + Shift + F7):强制步入,能进入任何方法,查看底层源码的时候可以用这个进入官方类库的方法。
Drop Frame (默认无):回退断点
Run to Cursor(Alt+F9): 运行到光标处,你可以将光标定位到你需要查看的那一行,然后使用这个功能,代码会运行至光标行,而不需要打断点。
Evaluate Expression (Alt + F8):计算表达式,后面会详细介绍。
6.第六部分: 方法的调用栈,点击 Show All Frames 就可以只展示业务的自定义方法。
7.第七部分:Variables (变量区),在变量区可以查看断点之前的变量的值。
8.第八部分:Watches 查看变量,可以将Variables区中的变量拖到Watches中查看 。
计算表达式
按 Alt+F8 或者点击就可以唤起计算表达式框了。如下图所示:
如上图所示,在表达式框中可以输入我们期望运行的语句,比如:可以写 user.getUserName()
来获取useName。
当然,也可以修改已经存在的值,比如当前的userName由 张三 改成 李四,使其生效之后继续往下运行。这个功能的作用是可以将传入的值改成我们期望的值继续后面的测试。
智能步入
如果一行代码中调用了多个方法,我们不想一个个方法运行的话,可以选中当前代码行,按Shift+F7唤起智能步入功能
如:if (StringUtils.isNotBlank(user.getUserName()))
这行代码调用了两个方法,唤起智能步入之后,我们可以自行选择要执行的方法,可以选择 isNotBlank方法,也可以选择getUserName方法。是不是非常的好用呢?
断点条件设置
断点条件设置也是一个非常好用的功能,想象如下场景:比如现在有个很大的集合,我要找出其中该集合中的某个对象,该如何断点呢,是一步步的循环下去么?当然不是的啦!如下图,找出集合userList中id>0的的对象只需要在表达式中写入user.getId()>0
即只有满足该条件,断点才会生效,是不是非常的实用,非常的方便呀。
多线程调试
我们在调试一个方法的时候,其他的请求是进不来的,这是因为Debug模式下默认是阻塞其余请求的,只有当本次调试结束之后才能结束阻塞。
当然这个也是可以调整的, 只需要在断点上选中 Thread即可。如果将Thread 设置为Default的话,则在调试的时候不会阻塞其他的请求。
远程调试
针对一些在本地无法复现的问题,我们可以通过远程调试的方式在测试环境或者线上环境复现。
操作步骤
其实操作步骤也很简单,只需要在Idea中设置远程连接,在Debug服务器中以调试模式启动服务。
1.在Idea中设置远程连接
首先是要在Idea中添加一个Remote ,如下图所示:我添加了一个名为testng-spring-boot的Remote。添加完成之后,大部分都可以直接使用默认设置,不过需要注意的:需要在Host中设置Debug服务器的地址。另外,如果默认的监听端口5005,与你项目的端口冲突了,则也需要修改。
在Idea中设置好之后,接着就是在Debug服务器以调试模式启动服务,启动命令如下:
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -jar testng-spring-boot-demo-0.0.1-SNAPSHOT.jar
其中:testng-spring-boot-demo-0.0.1-SNAPSHOT.jar 是本项目jar包名,你需要替换成你自己的jar包名。
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
这一段是直接将idea中默认生成的命令复制过来,这个命令是JDK5-8 这几个版本使用的,如果你的JDK版本是8以上的则可以通过如下方式切换
其中 jdwp:通知JVM使用(java debug wire protocol)来运行调试环境。参数同时有一系列的调试选项:
项目的启动结果如下图所示:
我们可以看到有 Listening for transport dt_socket at address:5005
这个日志输出,表明监听端口已经启动。
这样设置就可以正常的进行调试了,调试的方式就是选择前面设置的Remote,然后像下面这样点击
调试结果如下,当访问 /v1/user/get
接口时,远程Debug上能够正常的输出日志。
同时,断点也能够正常的进入。
远程调试的原理
说完了怎么进行远程调试,是不是还不过瘾,没关系,下面就介绍一下,远程调试的原理。我们都知道Java应用程序都是运行在JVM(虚拟机上的),运行的步骤是: 将Java文件----->编译生成的类文件(class文件)------>JVM加载类文件---->JVM运行字节码文件—>JVM翻译器翻译成各个机器认识的不同的机器码。因为Java程序统一以字节码的形式在JVM中运行,不同平台的虚拟机都统一使用这种相同的程序存储格式。所以Java程序具有了良好的跨平台性,也就为我们的远程调试提供了理论基础。因为使用了统一的字节码文件,所以,只需要本地类文件和远程服务器的类文件保持一致,两个JVM通过调试协议进行通信,默认的通信协议是通过Socket通信。
总结
本文首先对Idea的Debug做了一个详细说明,东西比较零散,比较多。但是,如果可以熟练掌握的话对我们的调试效率会有很大的提升。最后,介绍了远程调试。希望对读者朋友们有所帮助。