9个服务端提升debug效率的IDEA Debugger技巧

news2024/11/26 4:48:55

aeeefbc3b002964104a02c8b7cd1c10e.gif

不可否认,未来的一到两年中,程序员的编码体验将会发生剧烈的变化。作为一名一线开发,要如何提前准备,来应对这种变化呢?

d32bae5fb63fccdcbe130a9fda8ed5f1.png

前言

在AIGC时代,虽然深度学习模型可以仅通过一段注释来生成我们想要的代码,但是,最终要让代码跑起来的还是程序员自己,因此,调试代码,解决问题的能力相较于编码能力会变得愈发重要。

对于服务端而言,IDEA的Debugger几乎成为了调试代码的银弹。但是,笔者发现很多人在使用Debugger时,只使用了其中很小一部分功能。

在本文中,笔者将简要介绍一些自己整理的IDEA Debugger中一些鲜为人知,却能够在特定场景提升Debug效率的功能。

注意:本文不会涉及IDEA Debugger的基础操作,例如:

  1. 基本的Debug操作,包括但不限于:Step Over, Step Into, Step Out, Run to Cursor, Drop Frame等

  2. 基本的断点类型:条件断点、方法断点、线程/全局断点、字段断点、计数断点等

以上操作在各大论坛中均有优秀文章介绍。

f51c96c60973bde3bd63f37ea19231f8.png

断点

▐  不暂停断点

尽管很多文章已经提到过断点的非挂起功能,但是由于其太好用了,所以本文也单独列出,使用方法如下。

我们在创建断点时,进入断点配置界面后:

取消勾选Suspend,并填写Evaluate and log,此时,断点将会变为黄色。

03ad8b3b592cb7943243e8d3cca33242.png

当程序运行到断点时,代码不会中断执行,而是会直接在Debugger中打印出Evaluate and log中的信息:

37e22d420d6bf50770e7bf872670cbac.png

▐  异常断点

  • 普通断点的不足

当代码产生异常时,我们可以通过log看到异常捕获信息,然而,异常的捕获位置很可能和异常真实发生的位置相距甚远。

例如以下代码,ExceptionPoint的process方法调用了innerProcess方法,并在innerProcess方法中会产生运行时异常:

580df1a43c7ebcb8fac82e325dc10264.png

而异常捕获在上层的Filter类的main方法中:

931eeac78598f1d68902f50d786577a9.png

当异常产生后,产生的log为:

c53a54a4f51b1aa28b4b2b68a1f5e3e4.png

可以发现,log并没有打印出异常的堆栈信息,一旦发生这种情况,尽管我们可以定位到异常是哪里被捕获的,却很难定位到异常是在哪里呗抛出的。

  • 配置异常断点

为了获取异常被抛出的位置,我们可以使用IDEA中的异常断点,配置位置在断点面板的上面:

5aab573195010a0e5cd4ed5374c98148.png

选择好需要捕获的异常类型后,需要配置断点过滤:Catch class filters

51ee0a6a46099131c2d7785c2b7ce489.png

在断点过滤处,要输入捕获断点的类(本例为上层的Filter),配置完成后,重新Debug时,IDEA就会在异常将要抛出时进入断点:

c5070794e7ecf11a1ec68d271b8fa5dc.png

在异常抛出的位置,我们就可以很容易看出方法的入参出参,从而定位问题。

▐  依赖断点

  • 断点依赖的场景

有时,目标方法可能被多个方法调用,例如以下代码,work()方法同时被warmup和realWork方法调用。

16bd21d13d894d23aea2df8f123c1ce5.png

如果我们想让目标方法work()中的断点仅在被realWork()调用时才启用,要怎么办呢?

以下提供两种方法,这两种方法分别适用于不同的使用场景。

  • 前置条件断点

在方法realWork()中创建非挂起断点:

5961b2087c2c259959bb3d6594b331e2.png

在目标方法work()中如下位置增加断点依赖:仅当选中断点执行后再启用

6276ec3e08edc1fd6f561dc92e0a306f.png

完成上述配置后,Debug时,则仅当realWork()的断点被激活后,第二个断点才会被启用。

  • 调用过滤器

另一种方法是直接创建调用过滤器,不过这种方法需要当前暂停的断点正在被目标方法调用。

使用方法为:

在work()的断点行,Alt+Enter,在弹出的界面中,选择当前断点的调用条件:

976ca5015d562e382607aa3676808865.png

选择后,IDEA会自动填充到以下位置:

b0118743c5b912cd1aace9692491045d.png

同时,对于非静态方法,还可以选择Instance filters和Class filters,原理相同。

916ea62a37558b26d970816c613f94a9.png

▐  断点后悔药

如果我们好不容易按照上述方法设置了一些复杂的断点,却因为手滑点了一下,一不小心给删了,要怎么恢复呢?

以下提供三种方法,也分别适用于不同场景。

  • 标准的撤回操作

fff32d558ee797899e560bd3a9b401be.png

在如上位置,通过点击Restore Breakpoint,即可撤销删除最近删除的断点

  • 原地复活

如果我们已经进行了多个断点的删除操作,以至于上述撤回按钮已经失效了,要怎么办呢?

我们还可以在不小心删掉断点的位置再次创建一个普通断点,可以注意到,此时,IDEA会多出一个选项

fde135abaf8d933560c8d80738ce7176.png

点击Restore previous breakpoint,即可恢复原来的断点。

  • 一劳永逸的方法

既然我们经常一不小心删除断点,干脆修改左键为不删除断点不就好了?

IDEA也提供这一功能,位置在

68e60049be7f79b56facb3d8509199af.png

IDEA默认选择第一个,我们可以将其修改为第二个,修改后,左键点击断点,则禁用断点,按鼠标中键才会删除断点,彻底避免了手滑操作。

5af06ee6302b2f72bcde6336fbcadc99.png

渲染

▐  修改对象渲染器


  • 使用场景

有时,IDEA自带的变量渲染器并不能满足我们的需要。例如,我们创建一个继承JSONObject的类:

f456bb0c71eff6218690b89e6c1482ca.png

由于JSONObject继承了Map,所以IDEA默认是以Map的方式渲染的,因此,当我们运行以下代码时:

efdb60d1c30cc8ae86a91de984f3c2af.png

可以看到Debugger将bizObject渲染为了:

4dae5d90c08740aa127bfe5a23d18a55.png

可以看到,bizObject中的msg字段直接不见了,这当然不是我们想要的,为了获得真实的变量结果,我们可以手动修改IDEA的渲染方式,以下提供三种方法。

  • 简单修改

直接将Map渲染器修改为toString渲染器即可

31f052fbb19534d9ef9e474658932afe.png

修改后,Debugger的界面就会变为:

83f3a7ff8ca081debfd3401703156aee.png

该方法在一般情况下已经能够满足我们的需求。

  • 创建Class Level Watch

如果我们只想看BizObject中的msg字段,又不想修改渲染器的话,可以通过创建Class Level Watch来达到这一目的。

右键变量,点击New Class Level Watch

3412c56eaeb5f45dd4a0fec837796489.png

在弹出的输入框中输入想要查看的内容:

e3fbd2df894bbecd1ea843eff2882396.png

接下来,项目中所有类型为BizObject的类都会单独渲染一个msg字段。

fb6d231b295272e54c7a47e2079b0ffb.png

  • 创建自定义渲染器

如果上述方案都不能满足我们花哨的需求,也可以自定义渲染器:在指定的对象上,选择Create Renderer

53981ad91078ae317e0a90ab838dcdfa.png

在渲染器创建页面中,我们可以自定义渲染方式:

6323899ac9d7fac0c3483b858c76d772.png

当保存后,就可以看到IDEA按照我们想要的方式渲染对应类型变量了:

5f4a2bd2bd15095a15f09322fd38ebc1.png

如果渲染比较耗费资源,也可以勾选下面的On-demand开关,打开后,只有点一下对应变量才会执行渲染。

此外,如果想要将渲染配置同步给别人,也可以将配置抽取为注解放在对应类名上:

import org.jetbrains.annotations.Debug.Renderer;@Renderer(text = "name",childrenArray = "courses.toArray()",hasChildren = "courses.isEmpty()")public class Student {private String name;private ArrayList courses;Student(String name, ArrayList courses){this.name=name;this.courses=courses;}}

由于这一功能不是很常用,因此本文不再赘述,这里是注解说明https://www.jetbrains.com/help/idea/customizing-views.html#renderers。

▐  修改列表渲染器

当我们创建如下的列表时:

d937bbd095c10e9bb288808c20fa1103.png

在Debug界面,IDEA会将integers列表渲染为:

d3f44f6a92d547238a6bc6181b566e3e.png

可以看到,IDEA并没有渲染为null的元素,如果我们没有注意,并在接下来遍历这个list,很可能会产生NPE。

如何让IDEA显示为null的元素呢?方法如下:

b767582b4508a570c3b0fe2394729340.png

取消勾选后,IDEA就会将列表重新渲染为以下内容了。

5aa09faa443045a80c5eaff916dfb3bb.png

474e5c0e4e6dbc4d6160ebf11614ec14.png

定位

▐  标记

在一次请求链路中,有些对象在构造好后是不会轻易改变的,他们可能辗转穿梭于多个上下文中(例如User对象)。如果我们想要持续跟踪这个对象,则可以使用IDEA中的对象标记功能。

例如,我们创建两个上下文,分别为InputContext和OutputContext,其中都包含user字段。

e28363fca642c41b808eb3d65b753717.png

0d5f328b098094e03efddcf5373bc172.png

在一次处理中,代码从inputContex中获取user放到outputContext中

a69b539e65d8f78ac5d813f869917337.png

在我们进入断点后,可以在user对象上选择Mark Object:

b0426a6962a4191f7f78e3eec146accb.png

选择后,可以输入对于这个对象的标记(下例中将user用“mark”标记):

ebc25d25f37e0f00745ba247e0c37922.png

一旦一个对象被标记,这个对象在被销毁前就有了以下功能:

  1. 在任何debug页面,只要有引用指向这个对象,则会额外标记:

    f32efda896746f03d20379dcf7144cab.png

  2. 在任何线程,任何上下文中,我们都可以引用这个对象。

以下是一个在条件断点中引用user对象的实例:

6a1e45dc25c870d8073c7f1519830b8b.png

在上图中,可以看到,process2方法的上下文中并没有被标记的user对象,然而,如果我们使用标记名_DebugLabel,就可以访问之前标记user的对象,并且能够取出其name字段。

注意:变量标记在当前Debug结束后就会失效。

▐  引用

在多线程环境下,如果一个对象同时被两个线程执行写操作,很可能会出现线程并发问题,如果我们定位到一个对象可能出现了多线程问题,要如何知道这个对象被哪些线程引用呢?

方法也很简单,只需要找到对应变量,点击Show referring Objects,就可以找到所有线程中引用当前对象的对象。

295f049851b07743005c9a2c228919ae.png

▐  异步栈信息

当我们在同步代码中使用线程池来执行异步任务时,这个异步任务的栈和主线程是隔离的,此时,IDEA还可以看到主线程的栈信息么?

例如以下代码:main方法中创建了一个异步任务,调用了task方法;在task方法中,又启用了一个异步任务,调用了innerTask方法。

2e49024b1457d9986819552b3f08a05d.png

通过实践可以发现,虽然是有两层的异步调用,但是IDEA还是打印出了包括主线程在内的所有堆栈信息:

b6d7f2b14f2808bc5a7afbca6379be2b.png

只是每个Stack Frame之间增加了Async stack trace的提示,这是由于IDEA默认开启了Async stack trace,如果不想要看到除当前栈外的信息,可以在此处关掉这一功能:

f02dca0304334bd76680a06c6a1e3e5b.png

关掉后,所有异步任务就只会显示当前的栈信息了。

¤ 拓展阅读 ¤

3DXR技术 | 终端技术 | 音视频技术

服务端技术 | 技术质量 | 数据算法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/587501.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

.net 混淆工具

obfuscation tools .net 社区有很多混淆工具, 比如这个清单: https://github.com/NotPrab/.NET-Obfuscator 比较有名的商业工具有 .NET REACTOR https://www.eziriz.com/, 开源软件中, 最受欢迎的有: obfuscar https://github.com/obfuscar/obfuscar老版 ConfuserEx https://gi…

代码危机!如何利用自定义异常应对复杂业务逻辑

大家好,我是小米,在这篇文章中,我将和大家分享关于自定义异常的使用场景以及一个实际的电商项目案例。自定义异常在软件开发中起到了重要的作用,能够帮助我们更好地管理和处理各种异常情况。让我们一起来看看各个场景下如何使用自…

85.建立主体页面-第一部分

记住我们之前画的草图&#xff0c;根据我们的草图来构建初始的页面 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><meta n…

202313读书笔记|《山居七年》——我只想在广袤璀璨的星河里享受生的鲜活,独自飞,游走

202313读书笔记|《山居七年》——我只想在广袤璀璨的星河里享受生的鲜活&#xff0c;独自飞&#xff0c;游走 《山居七年》 作者张二冬&#xff0c;选择隐士山居是一种很自由随性的生活态度&#xff0c;我觉得这不是普通人可以拥有的&#xff0c;比如我&#xff0c;并未入世也…

Nginx学习1--介绍和安装

文章目录 官方网站常用功能核心组成下载安装源码安装linux包安装ubuntu安装docker安装 官方网站 http://nginx.org/ 官方文档 常用功能 静态资源部署处理静态文件、处理索引文件以及支持自动索引&#xff1b; Rewrite地址重写正则表达式 反向代理提供反向代理服务器&#xf…

大数据:配置云服务器,主机名映射和SSH免密登录,创建Hadoop用户,复制免密登录

大数据&#xff1a;配置云服务器&#xff0c;主机名映射和SSH免密登录&#xff0c;创建Hadoop用户&#xff0c;复制免密登录 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能很多算法学生都得去找开发&#xff0c;测开 …

十、Camera 启动流程分析

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、Camera 启动流程概览二、Launcher 跟Camera APP 交互三、Camera app 与FWK Camera Service 交互四、Camera FWK 与 Camera HAL 交互五、Camera FWK…

35岁,阿里6年,被打了低潜,已生无可恋,纠结该不该出去,40岁的人能不能给点建议?...

35岁是个转折点&#xff0c;许多人都在35岁时陷入迷茫&#xff0c;比如下面这位网友&#xff1a; 35岁&#xff0c;在阿里已经6年了&#xff0c;现在要混是可以混下去&#xff0c;但发展肯定是没有了&#xff0c;已经被老板打了低潜。目前被这个业务摩擦得已经生无可恋&#xf…

APP开发中的UI设计

UI设计是 APP开发中一个必不可少的部分&#xff0c;用户体验也是影响 APP产品成功与否的重要因素&#xff0c;用户体验包括用户的使用感受和操作感受。就 UI设计来说&#xff0c;它的主要内容有&#xff1a;界面、图标、颜色、字体、布局、页面布局等。 一个好的 UI设计可以增加…

通过extundelete实现CentOS6 ext4文件系统误删除文件的恢复

1.介质下载 路径&#xff1a; 链接&#xff1a;extundelete 提取码&#xff1a;ztj0 版本&#xff1a;extundelete.0.2.4 2.实验环境 1.CentOS6.8 系统版本命令&#xff1a; cat /etc/redhat-release 2.磁盘&#xff1a;/dev/sdb 磁盘查看命令&#xff1a; lsblk |g…

mysql数据备份-主从同步恢复

【1】数据库备份和恢复 1、xtrabackup-物理备份 全量备份主库数据&#xff1a;xtrabackup --backup --userroot --passwordxxx --port3306 --target-dir/comProject/backup/db/full_20220831 将full_20220831文件上传到从库服务器上 关闭存库服务&#xff1a;service mysqld …

将一维数组作为一列合并到二维数组中的numpy.column_stack()方法

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将一维数组作为一列合并到二维数组中 numpy.column_stack() 选择题 关于以下代码说法错误的一项是? import numpy as np a np.array([0,0]) b np.array([[1,2],[3,4]]) print("【显示…

C++ 线性数据结构系列之低调而强大的单调栈

1. 前言 单调栈是在栈基础上进行变化后的数据结构。除了遵循栈的先进后出的存储理念&#xff0c;在存储过程中还需保持栈中数据的有序性。 根据栈中数据排序的不同&#xff0c;单调栈分为&#xff1a; 单调递增栈&#xff1a;从栈顶部向栈的底部&#xff0c;数据呈递增排序。…

【JY】ABAQUS正交各向异性弹性本构模型

写在前文 材料的线弹性本构模型能够很好的描述处于工作荷载水平下的材料性能情况&#xff0c;后续材料的塑性理论也需要在弹性本构模型的基础上进行开展。由于砌体结构所采用的砌体材料具有明显的正交各项异性&#xff0c;故先从正交各向异性弹性入手&#xff0c;根据弹性理论中…

Java基础篇 | Java开发环境的搭建

✅作者简介&#xff1a;大家好&#xff0c;我是Cisyam&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Cisyam-Shark的博客 &#x1f49e;当前专栏&#xff1a; Java从入门到精通 ✨特色…

中创“六一”公益关爱活动 | 慈善守护童心,爱心筑梦未来

每一个孩子都是一朵花 有的盛开在春天&#xff0c;有的绽放在夏天 每一朵花&#xff0c;都有与众不同的美好 年年盛夏&#xff0c;如约出发&#xff1a; 在第73个“六一国际儿童节”来临之际&#xff0c;中创算力开展“六一公益关爱活动”&#xff0c;希望通过这样一个爱心…

我用低代码结合ChatGPT开发,每天多出1小时摸鱼

&#x1f449;腾小云导读 GPT 出现之后&#xff0c;很多人推测大量的软件都会因为其出现而重写。本文主要是低代码平台与 ChatGPT 结合的一些思考以及实践。期望与各位读者一起搭上 AI 这列快车&#xff0c;为开发提提速&#xff5e; &#x1f449;目录 1 背景 2 Demo 演示 3 思…

2022年软件测试人员调查统计——数据统计

1、软件测试从业人员的年龄分布 测试行业的主力军年龄分布主要是集中在 26-30 岁这个区间&#xff0c;这部分的群体承担着行 业发展的主导力量&#xff0c;占 43.2%。根据数据显示&#xff0c;被调查者中占比最多的是 26-30 岁区间的软件测试从业人员&#xff0c;26-30 岁的测试…

14 种免费 GIS 软件:在开源中绘制世界地图

如果你想绘制一幅世界地图&#xff0c;会选择什么GIS软件呢&#xff0c;ArcGIS、GlobalMapper这些都是国外比较出名的商业GIS软件&#xff0c;当然在国内很容易找到可用的版本&#xff0c;但是也可以使用免费的GIS软件完成所有操作。 这些免费的GIS软件为您提供了完成工作的效…

使用 VSCode SSH 公网远程连接本地服务器开发 - cpolar内网穿透

文章目录 前言视频教程1、安装OpenSSH2、vscode配置ssh3. 局域网测试连接远程服务器4. 公网远程连接4.1 ubuntu安装cpolar内网穿透4.2 创建隧道映射4.3 测试公网远程连接 5. 配置固定TCP端口地址5.1 保留一个固定TCP端口地址5.2 配置固定TCP端口地址5.3 测试固定公网地址远程 转…