优化的'printf'调试
阅读其他语言: English Español 한국어 Português
‘printf’调试,作为最常见的调试技术之一,尤其受欢迎,因为它几乎是在人们编写第一个程序时就会直观学会的。
‘printf’调试非常易于使用,因为你不需要任何特殊工具。当你遇到最初的错误,甚至还不知道什么是调试器时,自然而然会想到让程序一步步打印变量,在控制台中跟踪执行流程。
尽管这是一种最基本调试技术,但即使是经验丰富的开发者也频繁使用它。它可以帮助你调查各种问题,如不理想的程序段、不一致的状态、多线程问题等。
如我前面所提,这种技术并不需要使用特定的工具,如IDE。然而,如果你正在使用一个IDE,它可以让你在记录程序状态时更加高效。
本文展示的是IntelliJ IDEA的功能。 其他IDE可能有或没有类似功能。 如果你使用的是其他工具,请考虑查阅其文档, 查看这些功能是否同样可用。
实时模板
IntelliJ IDEA提供了实时模板,用于最常见的调试日志模式。要使用调试日志的实时模板,输入相应的缩写并按Tab键,IntelliJ IDEA将生成打印语句并插入到光标位置。
让我们来看几个例子。
记录方法参数
public static BufferedImage recolor(BufferedImage in, BufferedImage mask, int newColor) {
// 在这里输入 'soutp',然后按Tab
return null;
}
public static BufferedImage recolor(BufferedImage in, BufferedImage mask, int newColor) {
System.out.println("in = " + in + ", mask = " + mask + ", newColor = " + newColor);
return null;
}
记录值
public static double coolMethod(double parameter) {
double a = Math.random();
double b = Math.random();
// 在这里输入 'soutv',按Tab,然后选择值
return a * b * parameter;
}
public static double coolMethod(double parameter) {
double a = Math.random();
double b = Math.random();
System.out.println("b = " + b);
return a * b * parameter;
}
记录方法入口
public static BufferedImage recolor(BufferedImage in, BufferedImage mask, int newColor) {
// 在这里输入 'soutm'
return null;
}
public static BufferedImage recolor(BufferedImage in, BufferedImage mask, int newColor) {
System.out.println("ImageUtils.recolor");
return null;
}
日志断点
使用打印语句进行调试的一个缺点是它们引入了手动管理的开销。你不能快速地开启和关闭它们,并且绝对不想意外地提交并在生产环境中运行它们。
因此,如果需要为调试目的记录某些内容,建议使用日志断点,因为它们更易于管理。
要设置日志断点,按住Shift键,然后点击边距。与常规断点不同,它不会暂停程序的执行,而是输出到控制台。
默认情况下,它是表明程序到达这一行的消息。如果你更愿意记录当前堆栈跟踪或自定义表达式的结果,也可以在断点设置中的求值并记录 (Evaluate and log)复选框旁的选项中使用。
注意日志表达式的使用。评估那些引起副作用的表达式可能是新bug或意外行为的源头。此外,当在热点代码中使用时, 它们可能会显著减慢你的程序。
当日志断点变得很多时,可以在断点 (Breakpoints)对话框(运行 | 查看断点 – Run | View Breakpoints)中跟踪和管理它们:
你甚至可以为它们创建自定义组:
这有助于集中管理断点。例如,你可以创建一个与特定错误相关的组并保存以备后用。当问题解决时,只需将其关闭。这样,如果问题再次出现,你不必从头开始重新创建一切。只需再次打开该组即可。
频繁事件的日志记录
对于程序执行过程中经常发生的事件,记录每一次事件可能是多余的。这不仅会用消息淹没控制台, 而且大量的I/O交互可能会显著降低调试会话的速度。
对于这类事件,使用合格次数 (Pass count) 功能可能很有帮助。你可以在断点 (Breakpoints)对话框中访问它。
设置合格次数 (Pass count)到特定值后,相应的断点将仅在每n次命中时触发,确保日志记录不会成为麻烦。
总结
无论你是插入打印语句还是设置日志断点进行调试,现代工具都具有改善调试体验的特性。通过这篇文章,我希望确保你了解这些使整个过程更加愉快的小技巧。
祝调试愉快!