注:IDEA版本为2019.2.4
文章目录
一.Debug设置及窗口介绍
1.1 Debug设置及入口
在设置里勾选Show debug window on breakpoint,则请求进入到断点后自动激活Debug窗口
选择项目后,点击右边小甲虫图标或者shift +F9触发debug活动窗口
1.2 Debug窗口及功能简介
1-断点: 在左边行号栏右侧单击左键,或者快捷键Ctrl+F8 打上/取消断点。
1.1 移动断点
要移动断点,请将其拖动到目标行。
1.2 复制断点
要复制断点,请按Ctrl并将其拖动到目标行。
1.3 禁用断点
要临时禁用断点而不将其从项目中删除,请按住 Alt 键并单击装订线中的断点图标。
1.4 断点分组,例如,如果需要为特定问题标记断点,则可以将断点分组。
在“ 断点”对话框中(Ctrl+Shift+F8),选择要放置在组中的断点,然后选择“ Move to group| <group_name> /从上下文菜单创建新的或已经存在的组名。
20-Variables: 在变量区可以查看当前断点之前的当前方法内的变量,详见以下的“二.Variables变量及变量视窗”。
21-Watches: 查看变量,可以将Variables区中的变量拖到Watches中查看。
如果没有显示Variables,Watches等视窗,可以点击Debug窗口右上角按钮选择要显示的视窗
22-Debug窗口栏: 如果debug窗口栏所在的底层一行工具栏不显示,可在下图方法中选中Tool Window Bars
23-方法调用栈: 里显示了该线程调试所经过的所有方法,勾选右上角的漏斗图标Hide Frames From Libraries按钮,就不会显示其它类库的方法了,否则这里会有一大堆的方法。
以下是核心功能介绍
2-Rerun ‘xxxx’ Ctrl+F5 : 重新运行程序,会关闭服务后重新启动程序。
3-Update ‘XXX’ application Ctrl + F10:更新程序,一般在你的代码有改动后可执行这个功能。而这个功能对应的操作则是在服务配置里,如下图,按下快捷键后也会弹出提示选择操作类型。
4-Resume ProgramF9: 跳到下一个断点,没有的话直接运行结束。比如,你在第20行和25行有两个断点,当前运行至第20行,按F9,则运行到下一个断点(即第25行),再按F9,则运行完整个流程,因为后面已经没有断点了。
5- Pause Program : 暂停程序。
6-Stop ‘xxx’ Ctrl + F2:停止应用,main方法中点击一下关闭,web应用连续按两下,关闭程序。有时候你会发现关闭服务再启动时,报端口被占用,这是因为没完全关闭服务的原因,你就需要查杀所有JVM进程了。
7-View Breakpoints Ctrl+ Shift + F8: 查看所有断点及断点详细设置,详细说明请看 四.Breakpoints断点详细设置。
8-Mute Breakpoints: 哑的断点,选择这个后,所有断点变为灰色,断点失效,按F9则可以直接运行完程序。再次点击,断点变为红色,有效。如果只想使某一个断点失效,可以在断点上右键取消Enabled,如图下图,则该行断点失效,断点失效后变为空心圆圈。
9-Get Thread Dump: 获取线程的转储信息,列出一些线程状态。
10-Settings: 单击此按钮以打开菜单,其中包含以下选项:
Show Values Inline:开启后可在变量旁边查看变量的值。
Show Method Return Values:选择此选项可显示最后执行的方法的返回值。
Auto-Variables Mode:如果您希望IntelliJ IDEA调试器自动评估某些变量(断点处的变量以及断点前后的几行),请选择此选项。
Sort Values Alphabetically:选择此选项可按字母顺序对“Variables”窗格中的值进行排序 。
Unmute Breakpoints on Session Finish::选择此选项可在调试会话完成后重新启用所有禁用的断点。
11-Pin Tab: 单击此按钮固定或取消固定当前选项卡。您可能需要固定标签,以防止在此窗口中达到最大标签数时自动关闭标签。
12-Show Execution Point Alt+F10:显示执行点,如果你的光标在其它行或其它页面,点击这个按钮可跳转到当前代码执行的行。
13- Step Over F8:步过,一行一行地往下走,如果这一行上有方法不会进入方法。
14-Step Into F7:步入,如果当前行有方法,可以进入方法内部,一般用于进入自定义方法内,不会进入官方类库的方法。
15-Force Step IntoShift+Alt+F7:强制步入,能进入任何方法,查看底层源码的时候可以用这个进入官方类库的方法。
16-Step OutShift+F8:步出,从步入的方法内退出到方法调用处,此时方法已执行完毕,只是还没有完成赋值。
17-Drop frame:回退断点,具体详见 五.断点回退 。
18-Run to CursorAlt+F9:运行到光标处,你可以将光标定位到你需要查看的那一行,然后使用这个功能,代码会运行至光标行,而不需要打断点。如果光标行之前有断点,会在此断点上暂停。
19-Evaluate ExpressionAlt+F8:计算表达式,详见以下 三.Evaluate Expression计算表达式。
更多调试的方法,可以在Run按钮下查看
二.Variables变量及变量视窗
2.1查看参数值
- 参数所在行后面会显示当前变量的值,在以上的Settings->Show Values Inline可以打开/关闭。
- 光标悬停到参数上,显示当前变量信息,点击 + 号可以查看变量详情。
在Variables里查看,这里显示当前方法里的所有变量。
2.2设置修改变量值
当代码运行到一些变量时,发现此参数有错误,可以右键选择对应的变量,手动临时修改此参数的值(F2),如下,
2.3查看方法返回值设置
设置查看方法的返回值如下,即可查看调用方法的返回值情况。
2.4 Watches窗口参数
在Watches里,点击New Watch,输入需要查看的变量。或者可以从Variables里拖到Watche里查看。
三.Evaluate Expression计算表达式
3.1计算结果
选中要计算的内容,在Run菜单中或者Alt+F8弹出计算表达式窗口如下。
点击Evaluate按钮可以计算出选中内容的结果,这个表达式不仅可以是一般变量或参数,也可以是方法,调用的方法可以计算其返回值。
3.2临时修改参数内容
设置变量,在计算表达式的框里,可以改变变量的值,这样有时候就能很方便我们去调试各种值的情况。
四.Breakpoints断点详细设置
4.1主要参数说明
Ctrl+ Shift + F8或者点击左侧工具栏图标。
控制台输出如下:
过滤器说明如下:
Catch class filters:捕获类过滤器, 可以指定类名或类模式(带*通配符的字符串)。
如果通过类名指定了过滤器,则它指向该类本身及其所有子类。通过类模式指定的过滤器指向其完全限定名称与该模式匹配的类。
句法:
使用空格分隔类名和通配符号;要排除的类,请-在类名称前输入 -
例如,这-java.* -sun.*意味着不得为java和sun包中捕获的异常触发断点。
Instance filters: 实例过滤器,选择以限制特定对象实例的断点命中,语法同上。
Class filters: 类过滤器,选择以过滤必须击中断点的类,语法同上。
Pass count: 用于循环中,如果断点在循环中,可以设置该值,循环多少次后停在断点处,之后的循环都会停在断点处。如果同时设置了通过次数和条件,则IntelliJ IDEA首先满足条件,然后检查通过次数,以避免两个设置之间发生冲突。
Caller filters: 选择仅在从某个方法调用(或不调用)断点时才需要在断点处停止。
4.2异常捕获及定位
异常断点,通过设置异常断点,在程序中出现需要拦截的异常时,会自动定位到异常行。
点击 + 号添加Java Exception Breakpoints,然后输入需要断点的异常类型,添加异常断点,我这里捕获任何异常,如图下图。之后可以在Java Exception Breakpoints里看到添加的异常断点。增加过滤的类,否则捕获的异常可能是java类包存在或者抛出的异常。
代码中抛出空指针,出现空指针异常后,自动定位在空指针异常行。
五.断点回退
所谓的断点回退,其实就是回退到上一个方法调用的开始处,在IDEA里测试无法一行一行地回退或回到到上一个断点处,而是回到上一个方法。
5.1回退方式1
一种是Drop Frame按钮+F9(Resume Program),回退到方法断点处。
5.2回退方式2
第二种方式,在调用栈方法上选择要回退的方法,右键选择Drop Frame ,回退到该方法的上一个方法调用处,此时再按F9(Resume Program),可以看到程序进入到该方法的断点处了。
但有一点需要注意,断点回退只能重新走一下流程,之前的某些参数/数据的状态已经改变了的是无法回退到之前的状态的,如对象、集合、更新了数据库数据等等。即已经对全局状态所做的更改将不会恢复,而只会重置局部变量。
六.中断断点
有些时候,我们看到传入的参数有误后,不想走后面的流程了,怎么中断这次请求呢(后面的流程要删除数据库数据呢…)。
可以通过Force Return,即强制返回来避免后续的流程,如图。也可在Run下拉菜单进入。
点击Force Return,弹出Return Value的窗口,我这个方法的返回类型为Message,所以,我这里直接返回new Message()来强制返回,从而不再进行后续的流程。或者里面的表达式可以设置为其他null等表达式。
注:输入表达式确定后,往往还需要按F9(Resume Program)才能完全终止请求操作。
七.分析Java Stream操作
Java 8 Streams有时可能难以阅读和调试,因为要了解程序是如何到达特定输出的,您可能需要插入其他断点,并分析流中的每个转换。
此功能仅适用于项目文件。不能使用Java Stream Debugger调试库或反编译的代码。
当调试器在Stream API调用链之前或之内停止时,点击跟踪当前流链图标Trace Current Stream Chain 。
在评估了当前数据流之后,您可以直观地看到每个转换中每个元素发生了什么,以及它的值在经过数据流中的所有步骤时如何变化:
调试流跟踪拆分视图
单击“ 平面模式”按钮可在一个视图中一次查看所有操作:
调试流跟踪平面视图
八.主动抛出异常(不修改代码)
IntelliJ IDEA使您可以从程序中的特定位置引发异常,而无需修改代码。
从“ Frames”视图中所选方法的右键菜单中 选择“ 抛出异常”,然后指定表达式:
九.检测死锁
当两个线程之间的冲突导致彼此根本无法工作时,就会发生死锁。一旦发生,可以通过查看所有线程的 Frames来轻松发现死锁。我们可以通过使用Thread dump来做到这一点 。如果我们知道我们正在陷入死锁,那么运行模式甚至比调试更可取。这是因为我们完全不会干涉这种方式的执行,并且快照将是应用程序的Java线程转储的输出。线程转储可以检测死锁并发出警告。例如,在下面的转储中,我们可以看到该进程在PublisherThread(卡在第44行)和SubscriberThread(在第78行)之间发现了1个死锁。
在此示例中,我们可以看到两个线程都被卡在等待一个锁,这意味着另一个线程没有释放这些锁。我们还可以看到两者都在等待不同的锁,因为同步器ID是不同的。顶部的死锁摘要提供了更多信息,它告诉我们什么线程持有每个锁。我们可以看到两个死锁线程持有另一个线程试图获取的锁。
这应该已经为我们提供了有关死锁如何发生的大量信息。如果仍然不清楚我们的代码如何达到死锁,则可以在遇到线程转储提供的行之前尝试使用断点进行调试。当我们有什么错误时,我们可以尝试使用断点之间的依赖关系来重现场景。
现在,我们可以 在其中一个线程上创建一个“ Suspend Thread”断点,并使用另一个线程转储快照来验证另一个线程是否达到了死锁位置。
另一个选择是在两个线程上放置挂起线程断点,并在它们之间切换。检查的状态Publisher,并Subscriber 在这个例子告诉我们,造成混乱的状态。
当我们检查锁实例时,我们可以看到并发代码实际上是正确的,但是当将它们传递给两个对象时,我们混淆了读锁和写锁。查看上图中的锁实例ID。
确实,当我们随后检查构造(在其中注入了这些锁)时,我们可以看到该错误:
ThreadGroup threadGroup = new ThreadGroup("Demo");
new Thread(threadGroup, new Subscriber(messageQueue, readLock, writeLock), "SubscriberThread").start();
//passing locks in the wrong order will cause deadlock between publisher and subscriber
new Thread(threadGroup, new Publisher(messageQueue, writeLock, readLock), "PublisherThread").start();