JAVA代码调试方法介绍(基于IntelliJ IDEA)
1. window快捷键:
- 切换为行断点: Ctrl+F8
- 断点属性编辑: Ctrl+Shift+F8
2. 断点类型与设置
行断点(line breakpoints)
- 在到达设置断点的代码行时暂停程序。这种类型的断点可以设置在任何可执行的代码行上。
字段断点(field breakpoints)
-
当指定的字段被读取或写入时暂停程序。这允许你对与特定实例变量的交互作出反应。例如,如果在一个复杂的过程结束时,你的某个字段出现了明显的错误值,设置一个字段观察点可能有助于确定故障的来源。
-
鼠标右键点击该断点图标 ,弹出该断点配置,会有Field access和Field modification选项,此选 项是字段类型断点特有的,分别对应访问该字段或修改该字段触发断点,两项同时选中,则访问与 修改该字段都会触发断点。
方法断点(method breakpoints)
在进入或退出指定的方法或其实现之一时暂停程序,允许你检查该方法的进入/退出条件。
- 当断点加在class类名这一行,且该类中没有编写构造函数(只有默认无参构造函数),当调用默认 无参构造函数时会触发此断点,程序挂起,故该断点虽然图标是行断点类型图标,但实际上属于方法类型断点。
- 鼠标右键点击该断点图标 ,弹出该断点配置,会有Emulated、Method entry、Method exit选 项,此选项是方法类型断点特有的。Emulated勾选中,会将方法断点优化成方法中第一条和最后 一条语句的行断点,这样会优化调试的性能,因此在IDE中会默认选中。
- 通过匹配符批量添加方法断点,在断点列表页
匹配符示例:
Class | Method | Result |
---|---|---|
* | 匹配所有类的print() 方法 | |
Printer | * | 匹配Printer类中的所有方法 |
Printer | set* | 匹配Printer类中的所有方法名set开头的方法 |
异常断点(Exception breakpoints)
- 异常断点分为两种,一种是Any Exception,任意Throwable异常被捕获或未被捕获就会触发断 点,另一种是指定类型的异常及其该异常子类被捕获或未被捕获会触发断点,该类型断点图标
- 鼠标右键点击该断点图标,弹出该断点配置,会有Caught exception和Uncaught exception选项,此选项是字段类型断点特有的,Caught exception选项选中时,当指定的异常被捕获时,触发断点程序挂起,Uncaught exception选中时,当指定的异常未被捕获时,触发断点程序挂起。
3. 断点控制
断点删除
- 所有类型断点:断点设置中移除对应的即可。
- 快捷移除:行位置鼠标左键单击即可移除(异常断点除外)。
建议:为了避免意外删除断点并丢失其参数,通常选择点击鼠标中键来删除断点。要做到这一点,请进 入 “设置/首选项”|“构建、执行、部署”|“调试器”,选择 "拖到编辑器 "或用鼠标中键点击。点击一个断点 将启用或禁用它。
断点静音
如果某些时候不需要在断点处停留一段时间,可以将断点静音。这样就可以在不离开调试器会话的情况
下恢复正常的程序操作。之后,可以解除中断点的静音,继续调试。断点静音会静音所有断点
- 在断点调试窗口,点击断点静音按钮
启用/禁用断点
正常通过断点删除的断点,会连同当时断点的内部所有配置一并删除。如果想暂时关闭一个断点,后续可能还会使用,这是一个很好的选择
断点移动/复制
断点移动:鼠标左键拖动
断点复制:按住ctrl,鼠标左键拖动
4. 断点属性配置
鼠标操作:右键断点:More(Ctrl+Shift+F8)
快捷键:Ctrl+Shift+F8
快捷键:光标所在行 Alt+Enter
断点有许多属性配置,如下图所示,下面将会对各个属性的作用以及使用进行说明。
Enabled
- 表示是否启用该断点,选中表示启用,取消选中表示不启用。
Supend
- 当断点的 Suppend 属性被勾选,触发该断点时,会触发程序挂起,当该属性未选中时,程序触发该 断点时,程序不会挂起,常用于输出一些表达式结果日志。
- 当断点的 All 属性被勾选,触发该断点时,会挂起所有线程
- 当断点的 Thead 属性被勾选,触发该断点时,只会挂起触发该断点的那个线程,不影响其他线程
当需要在不暂停程序的情况下记录一些表达式时(例如,需要知道一个方法被调用了多少次时),或者需要创建一个主断点,在击中后启用附属断点时,非暂停性断点是非常有用的。实际生产实践中,可用于调试多线程并发的问题
Condition
- 可以输入一段能获得true或false的表达式,程序运行到断点处,且表达式条件为true才会触发断点
Log
下面三个属性选项经常配合 Suppend 属性一起使用,用于在不挂起的情况下,输出一些想要的日志信 息
- Breakpint hit message :控制台输出触发端点的日志信息,类似如Breakpoint reached at ocean.Whale,main(Whale.java:5)
- Stack trace :输出触发断点时的堆栈信息
- Evaluate and log :计算表达式结果并输出表达式结果到控制台,表达式的计算基于断点所在行的上下文,表达式的语句可以是字符串字面量,如“我是字符串”,也可以是方法调用,如users.size(),也可以是多行语句块,表达式的结果取自return语句,如果没有return语句,会取表达式中的最后一行语句。
Remove once hit
- 是否在断点触发后移除该断点,后续不在触发
Disable until hitting the following breakpoint
- 指定在另一个断点触发后,该断点才启用,若该断点启用后,并且被触发,
场景:当只需要在某些条件下或某些操作后暂停程序时,这个选项很有用。在这种情况下,触发断点通常不需要停止程序的执行,而是做成非暂停状态。
Filters
前边说的大都数属性,都只针对方法程序运行上下文。此属性更多关注通过过滤掉类、实例和调用者方法来微调断点操作,只在需要时暂停程序。有如下几种过滤方式: - Catch class filters :此选项只对异常类型的断点可用,可以让程序只在指定类和子类中抛出的 异常才会触发断点或者不在指定的类和子类中触发断点(即排除一些类,排除通常以 - 开始,例如-package.ClassName),
- Instance filters:只有指定实例id号可以触发断点,多个实例id号以逗号隔开,实例id号可以在 Variables和Memory面板中查看
- Class filters :可以让程序只在指定类和子类中才会触发断点或者不在指定的类和子类中触发断 点(即排除一些类)。
- Caller filters:根据调用者来进行过滤,需指定方法的全限定名(包含方法签名),例如mypackage.MyObject.addString(Ljava/lang/String;)V
配置 | 说明 |
---|---|
-package1.Class1.method1([Ljava/lang/String;)Ljava/util/List; | 此处是 caller filter 的配置示例, 该示例中排除了来自 package1.Class1类中method1方法,并且方法签名是:List method1(String[] input)的调用(即不触发断点) |
package1.Class1 *s2 -package3.Class3 | Class filters 和 catch class filter 中的配置示例。该示例中,断点仅在 package1.Class1以及全限定名以 s2 结尾的类中可以被触发,并且不在 package3.Class3中触发( - 开头表 示排除) |
-java.* -sun.* | Class filters 和 catch class filter 中的配置示例,该示例排除了 java and sun包下的所有类(``- 开头表示 排除) |
Pass count
- 勾选中并输入一个正整数N,N>=1,那么程序会每N次命中断点才会触发挂起,如果同时设置了condition与pass count 属性,idea会优先判断 condition 表达式,再判断 pass count 是否满足,下例中,pass count中传入的是15,每15次命中断点才会触发断点,挂起程序