第3章 在NetBeans中调试应用程序
在开发程序的时候,可能会出现各种错误,虽然编译器会帮助开发人员找到一些语法错误,但是对于一些逻辑错误或者算法上的错误,就只能利用NetBeans的调试技术进行分析和解决了。本章将讨论NetBeans如何调试应用程序、进行单步跟踪、查看本地变量等内容。
本章主要内容
● 设置和管理断点
● 如何执行单步跟踪
● “监视”窗口的使用
● 局部变量窗口
● 如何在调试时修改代码
本章亮点
● NetBeans各个类型断点的设置方法
● 各个调试窗口的使用
● 如何计算表达式
3.1 在NetBeans中调试应用程序
调试是检查应用程序是否存在错误的过程。可以通过在代码中设置断点和监视,然后在调试器中运行代码来完成调试过程。NetBeans集成开发环境使用Sun Microsystems JPDA调试器来调试程序。选择“运行”→“步入”命令或者按下快捷键F7,就可以进入调试会话界面。此时,程序会停止在代码的入口处,如图3-1所示。
图3-1 调试会话界面
另外,也可以选择“运行”→“运行至光标”命令或者按下快捷键F4,可以将程序运行到源代码编辑器中光标所在的位置并暂停程序。
在启动调试会话时,所有相关的调试器窗口都将自动出现在屏幕的底部。在“输出”窗口中会添加一个“调试器控制台”标签,用于显示来自当前会话调试器的消息,并包括指向源代码的超级链接。在“输出”窗口中可以使用如下的快捷菜单命令。
● “复制”命令:将选定文本复制到剪贴板。
● “查找”命令:在窗口中查找字符串。
● “查找下一个”命令:查找在“查找”中指定的搜索项的下一个出现位置。
● “自动换行”命令:如果选中该选项,文本将在窗口宽度位置换行。如果未选中,则必须扩展窗口以查看比窗口更宽的文本。
● “另存为”命令:提示您输入可以保存窗口内容的文件。
● “清除”命令:清除选定标签化窗口的内容。
● “关闭”命令:完全关闭“输出”窗口。
使用以下任何一种方式都可以关闭调试会话:
● 选择“运行”→“完成调试器会话”命令;
● 按下Shift + F5组合键;
● 单击“调试”工具栏中的“完成调试器会话”按钮。
3.2 设置和管理断点
断点是源代码中的标志,它会通知调试器停止执行程序。当程序在断点处停止时,开发人员可以执行诸如检查变量值和单步执行程序等操作。
3.2.1 断点类型
NetBeans中支持以下几种断点类型。
● 行断点:可以为某一个代码行设置断点,这样当运行到该行时就会中断程序的执行。
● 类断点:可以在将类装入虚拟机和/或从虚拟机中卸载类时中断程序的执行。
● 异常断点:可以在捕捉到特定异常、未在源代码中处理特定异常或遇到任何异常(无论程序是否处理错误)时中断程序的执行。
● 变量断点:可以在访问(例如,将变量作为参数来调用方法)或修改特定类和字段中的变量时中断程序的执行。
● 方法断点:每次执行该方法时都将中断程序的执行。
● 线程断点:可以在线程开始和/或停止时中断程序的执行。
说明:除了行断点之外,所有Java断点都是全局定义的,因此它们会影响所有集成开发环境项目(这些项目包含设置了断点的源)。例如,如果在某个项目中的com.mycompany. MyOkCancelDialog上设置了类断点,则在其他项目(包含该类)的调试会话期间,集成开发环境每次遇到该类时都会停止执行。
如果已经设置了断点,对于主项目,可以选择“运行”→“调试主项目”命令或者按下快捷键F5进入调试会话,程序将中断在遇到的第一个断点的位置。
对于非主项目,可以在“项目”窗口中右键单击该项目,然后选择弹出菜单中的“调试项目”命令进入调试会话,程序将中断在遇到的第一个断点的位置。
对于某个文件,可以在“项目”窗口中选择任何可运行的文件,然后选择“运行”→“运行文件”→“调试<选中的文件名>”命令或者按下Ctrl + Shift + F5组合键进入调试会话,程序将中断在遇到的第一个断点的位置。
3.2.2 添加行断点
行断点的设置比较简单。在源代码编辑器中单击要设置断点行的左边距,或者按Ctrl + F8组合键。添加断点后,设置断点的行会以红色突出显示,并在左边距中显示一个的红色的方框,如图3-2所示。再次单击该行的左边或者按Ctrl + F8组合键将取消该断点。
图3-2 设置行断点
3.2.3 添加类断点
如果要设置除了行断点以外的其他类型的断点,可以在源代码编辑器中选择要设置断点的代码元素。例如,如果要在类MyOkCancelDialog上设置类断点,请在类声明中选择该类名。然后,选择“运行”→“新建断点”命令或者按下Ctrl+Shift+F8组合键,打开“新建断点”对话框,如图3-3所示。
图3-3 在“新建断点”对话框中添加类断点
添加类断点的各个参数说明如下:
● “调试器”下拉列表框:选择调试器的类型,如果是调试Java程序,应该选择Java调试器。
● “断点类型”下拉列表框:说明当前的断点类型为类断点。如果要设置为其他的断点类型,可以通过下拉列表框进行选择。
● “类名”文本框:用于指定为哪个类(包含包名的全路径)设置类断点。
● “停止条件”下拉列表框:用于指定触发断点的操作,可以有如下的选项。
类装入:将类加载到虚拟机时触发断点的操作。
类卸载:从虚拟机卸载类时触发断点的操作。
类装入和卸载:将类加载到虚拟机时或者从虚拟机卸载类时触发断点的操作。
● “排除类”复选框:选中该复选框后,可以在后面的文本框中输入要排除的类。被排除的类中的断点将会被排除,即不会在这些断点处暂停执行。
● “进行命中计数时中断”复选框:选中该复选框可以在后面指定断点触发的频率和时间。例如调试一个循环语句时,如果不希望每个循环都触发断点,可以使用该选项,设置循环执行100次以后才会触发断点。
● “暂停”下拉列表框:指定到达断点时调试的程序中要暂停的线程,可以有如下的选项。
无线程(继续):将继续执行。
所有线程:所用线程都将暂停执行。
断点线程:到达断点时的当前线程暂停执行。
● “打印文本”文本框:将在“输出”窗口的“调试器控制台”视图中打印指定的消息。这里将打印类断点的类名。打印消息中可以使用特殊的标记,表示特殊的含义。标记的定义以及使用方法如表3-1所示。其中 或文本表示可将标记用于该断点类型。 表示该标记不能用于该断点类型。
表3-1 断点打印消息中的特殊标记
3.2.4 添加方法断点
在源代码编辑器中,选择要设置断点的方法,然后,选择“运行”→“新建断点”命令或者按下Ctrl+Shift+F8组合键,打开“新建断点”对话框,如图3-4所示。
图3-4 在“新建断点”对话框中添加方法断点
添加方法断点的参数和类断点参数基本一致。如果选中“给定类的所有方法”复选框,则会将断点应用于指定类的所有方法。如果取消该复选框,则要在“方法名称”文本框中输入断点的方法名称。
3.2.5 添加异常断点
在如图3-3所示的“新建断点”对话框中,从“断点类型”下拉列表中选择“异常”选项,创建一个异常断点,如图3-5所示。
图3-5 在“新建断点”对话框中添加异常断点
其中,“操作”复选框中各个参数的含义请参考第3.2.3节关于添加类断点的参数说明。其他添加异常断点的参数说明如下。
● “异常类名”文本框:选择或者输入要设置异常断点的异常类或异常超类的名称。
● “停止条件”下拉列表框:指定触发断点的操作,可以有如下的选项。
捕捉到:仅在捕捉到异常时中断程序的执行。
未捕捉到:仅在未捕捉到异常时中断程序的执行。
捕捉到或未捕捉到:所有异常处都中断程序的执行。
● “过滤抛出异常的类”复选框:选中该复选框,可以过滤触发异常断点的类。此时,可以在下面的“匹配类”文本框中输入允许触发异常断点的类,只有输入的这些类中的异常断点才会被触发。当然,也可以在“排除类”文本框中输入希望排除的类名字,这些被排除的类中的异常断点将不会被触发。
3.2.6 添加线程断点
在如图3-3所示的“新建断点”对话框中,从“断点类型”下拉列表中选择“线程”选项,创建一个线程断点,如图3-6所示。
图3-6 在“新建断点”对话框中添加线程断点
在“停止条件”下拉列表框用于指定触发断点的操作,可以选择如下的选项。
● 线程开始:在线程开始时触发断点。
● 线程停止:在线程停止时触发断点。
● 线程开始或停止:既在线程开始时触发断点,又在线程停止时触发断点。
3.2.7 添加字段断点
在源代码编辑器中,选择要设置断点的字段,然后,选择“运行”→“新建断点”命令或者按下Ctrl+Shift+F8组合键,打开“新建断点”对话框,如图3-7所示。
图3-7 在“新建断点”对话框中添加字段断点
其中,“操作”分组框中各个参数的含义请参考第3.2.3节关于添加类断点的参数说明。其他添加异常断点的参数说明如下。
● “类名”文本框:包含字段(该字段要被设置为字段断点)的Java类文件全路径名。也可使用星号作为类名。例如,如果将java.lang指定为包名,并将*作为类名,则断点将会应用于java.lang包的所有类。
● “字段名”文本框:要设置字段断点的字段的名字。
● “停止条件”下拉列表框:指定触发断点的时间,可以有如下的选项。
字段访问:查询字段时,将中断程序的运行。
字段修改:修改字段时,将中断程序的运行。
字段访问或修改:在查询或者修改字段时,都会中断程序的运行。
3.2.8 断点的管理
NetBeans集成开发环境提供了“断点”窗口,以便于对断点进行管理。选择“窗口”→“调试”→“断点”命令或者按下Alt + Shift + 5组合键,打开“断点”窗口,如图3-8所示。
图3-8 “断点”窗口
在名称列表中,列出了所用的断点。选中某个断点,然后单击右边的启用列,可以禁止或者启用某个断点。另外,在“断点”窗口中右键单击某个断点,然后选择弹出菜单中的“启用”或“禁用”命令也可以启用或者禁止某个断点。在“断点”窗口中单击右键,然后选择弹出菜单的“全部启用”或“全部禁用”命令则可以启用或者禁止全部的断点。
“断点”窗口弹出菜单中的“定制”命令可以打开“定制断点”对话框,对断点进行修改。“定制断点”对话框和“新建断点”对话框基本一样,请读者参考“新建断点”对话框的使用方法。
“断点”窗口弹出菜单中的“设置组名称”命令可以打开“设置断点组的名称”对话框,如图3-9所示。
图3-9 “设置断点组的名称”对话框
在“组名称”文本框中输入任何的组名字,单击“确定”按钮就可以把一个断点分到这个组中。如果在集成开发环境中设置了很多断点,则可以将这些断点归到不同的组,这样就可以将它们作为一个单元进行启用、禁用和删除操作。图3-10 是对断点进行了简单分组后的显示界面。
图3-10 对断点进行分组后的“断点”窗口
3.3 单步执行
实际开发中,断点一般都要和单步执行配合进行调试。NetBeans提供了如下的几种单步执行方法。
● 越过:单步执行一行源代码,如果源代码行包含调用,则执行整个例程而不单步执行单个指令。
● 步入:单步执行一行源代码。如果源代码行包含调用,则进入该调用例程,在执行例程的第一条语句之前停止。如果用“步入”方法启动调试会话(即选择“运行”→“步入”命令),程序会在main入口方法的第一行停止执行。
● 步出:单步执行一行源代码。如果源代码行是某个例程的一部分,则会执行该例程的其余各行,然后停止在调用该例程的行。
在调试过程中,这三种方法需要互相配合使用。例如,图3-11所示的调试会话中,执行越过命令,代码将停止在第27行。注意,如果此时仍然执行越过操作,则会执行到第28行。这里需要查看getReturnStatus方法内部的执行情况,因此执行步入命令,代码将停止在第35行。在检查完getReturnStatus方法后,执行步出命令,程序将会返回第27行。
图3-11 单步执行示例
表3-2给出了不同单步调试方法的执行方法。
表3-2 单步调试的执行方法
说明:在调试会话中,如果选择“运行”→“继续”命令(快捷键Ctrl + F5),或者选择“调试”工具栏中的“继续”按钮 ,则会继续执行代码一直到程序结束或者遇到下一个断点。
3.4 查看变量和表达式的值
在进行调试的时候,有时候需要知道变量和表达式的值,以确认执行得是否正确。NetBeans的调试会话支持查看变量和表达式的值。
3.4.1 在代码编辑器中直接查看
调试会话中,在程序中断执行后,如果把鼠标放在某个变量的上面,就可以显示该变量的值,如图3-12所示。
图3-12 查看变量的值
如果要查看某个表达式的值,则可以选中这个表达式,然后把鼠标放在选中的表达式上。此时会显示表达式以及表达式的值,如图3-13所示。
图3-13 查看表达式的值
3.4.2 使用“监视”窗口查看
NetBeans还支持创建监视,通过监视在程序执行期间跟踪变量或表达式值的变化。创建监视通过“新建监视”对话框实现,如图3-14所示。下面的三种方式都可以打开“新建监视”对话框:
图3-14 “新建监视”对话框
● 在源代码编辑器中选择变量或表达式,单击鼠标右键,然后选择弹出菜单中的“新建监视”命令;
● 按下Ctrl + Shift + F7组合键;
● 选择“运行”→“新建监视”命令。
在“监视表达式”文本框中输入要被监视的表达式,然后单击“确定”按钮,表达式将被添加到“监视”窗口,如图3-15所示。
图3-15 “监视”窗口
“监视”窗口列出了变量和表达式的全部监视。默认情况下,“监视”窗口将在每次启动调试会话时自动打开。也可以通过选择“窗口”→“调试”→“监视”命令来打开“监视”窗口。
在调试会话时,“监视”窗口中的变量和表达式的值会随着代码的执行而改变。当更改当前上下文时,“监视”窗口将进行更新,以显示对应于该上下文的监视值。
“监视”窗口的上下文菜单中,“删除”命令用于从“监视”窗口中删除选定的监视;“全部删除”命令用于从“监视”窗口中删除所有的监视;“属性”命令会打开一个对话框,修改监视表达式。
3.4.3 使用“局部变量”窗口查看
NetBeans的“局部变量”窗口列出了当前调用中的局部变量,如图3-16所示。默认情况下,“局部变量”窗口将在每次启动调试会话时自动打开。也可以通过选择“窗口”→“调试”→“局部变量”命令来打开“局部变量”窗口。
图3-16 “局部变量”窗口
“局部变量”窗口中列出了每个局部变量的名称、类型和值。可以单击名称左边的控件展开或折叠变量。如果对象类型以带下画线的蓝色文本显示,则单击文本将跳转至源代码中的对象类型。单击“值”单元格可以直接在“局部变量”窗口中编辑值。
3.5 计算表达式
在调试会话中,还可以计算一些代码中不存在的表达式。NetBeans会根据当前上下文会话中相关变量的值计算出表达式的值。当调试会话上下文发生变化后,表达式的值也会随着变化,以反映最新的值。
在调试会话中,选择“运行”→“计算表达式”命令或者按下Ctrl + F9组合键,打开“计算表达式的值”对话框,如图3-17所示。这里输入表达式“returnStatus==0”,然后单击“求值”按钮。此时会在“结果”列表中显示计算的结果。单击“监视”按钮则会在“监视”窗口中添加表达式的监视。
图3-17 “计算表达式的值”对话框
“计算表达式的值”对话框可以计算任何表达式的值,以查看当前方法的局部变量、类变量以及方法调用的值。如果计算的方法会更改全局变量,在调试会话中也会更改该全局变量的值。
3.6 在调试模式修改代码
NetBeans集成开发环境中可以支持在会话模式修改代码,并且在不退出调试会话的情况下进行编译并重新装载更新后的代码。在调试会话时,添加如图3-18所示的第230 行代码,然后选择“运行”→“应用代码更改”命令。
图3-18 在调试会话中修改代码
NetBeans会重新编译代码,并装载更新后的代码。在“输出”窗口中将添加一个新的标签,并显示代码修改的过程,如图3-19所示。
图3-19 “输出”窗口中的代码修改信息
3.7 NetBeans的调试窗口
在前面几节中已经介绍了一个NetBeans调试窗口的使用方法,下面介绍其他几个调试窗口的使用,包括“类”窗口、“调用栈”窗口、“线程”窗口、“会话”窗口和“源”窗口。
3.7.1 “装入的类”窗口
“装入的类”窗口显示已装入虚拟机中所有类的分层结构,此虚拟机承载当前调试的程序。“类”窗口的内容取决于当前上下文。更改当前会话时,“类”窗口将更新以显示该会话的类。可通过选择“窗口”→“调试”→“装入的类”命令来打开“装入的类”窗口,如图3-20所示。
图3-20 “装入的类”窗口
在“装入的类”窗口中,双击某个类可以打开实例窗口,如图3-21所示。在这个窗口中可以查看类的字段、引用实例等内容。
图3-21 类的实例窗口
3.7.2 “调用栈”窗口
“调用栈”窗口列出了执行当前线程期间的调用序列。可通过选择“窗口”→“调试”→“调用栈”命令或者按下Alt + Shift + 3组合键打开“调用栈”窗口,如图3-22所示。
图3-22 “调用栈”窗口
“调用栈”窗口中,每个调用提供的信息包括:调用名称和调用当前执行语句的行号。如果文件名和行号显示为带下画线的蓝色文本,则表示文本将链接到该调用的源代码。
标有 图标的线程是当前线程最近执行的调用。在“调用栈”窗口中双击某个调用,或者选择某个调用上下文菜单的“激活”命令,会激活该调用,同时调用的图标会变为。
选择“运行”→“栈”→“弹出最顶层调用”命令,将调用从调用栈中删除。程序计数器被移动到执行删除调用指令的前一行。如果源代码可用,源代码编辑器的焦点将置于该行。继续执行程序时,会重复该调用。
在“调用栈”窗口中,右键单击想要保留在调用栈顶层的调用,然后选择弹出菜单中的“弹出到此处”命令,将会从调用栈中删除选定调用之上的所有调用。程序计数器被移动到执行删除调用指令的前一行。如果源代码可用,则将源代码编辑器的焦点设置为该行。继续执行程序时,会重复该调用。
3.7.3 “线程”窗口
在当前会话中创建的所有线程都将显示在“线程”窗口中。对于Java应用程序来说,此列表还包括应用程序中的线程组。选择“窗口”→“调试”→“线程”命令或者按下Alt + Shift +7组合键,打开“线程”窗口,如图3-23所示。
图3-23 “线程”窗口
在任何给定时间,都只有一个线程是当前线程,当前线程的图标为。默认情况下,当前线程是当前会话内调试器从中获得控制的线程。在“线程”窗口中,双击任何线程,或者选择线程上下文菜单的“激活”命令,都可以将线程设置为当前线程。
如果需要暂停某一线程,可以在“线程”窗口中右键单击该线程,然后选择“暂停”命令;如果需要恢复某一线程的执行,可以在“线程”窗口中右键单击该线程,然后选择“恢复”命令。
在“线程”窗口中右键单击某个线程,然后选择“转至源”命令,会在源代码编辑器中打开对应的代码。
3.7.4 “会话”窗口
“会话”窗口列出当前在NetBeans集成开发环境中运行的调试会话。选择“窗口”→“调试”→“会话”命令,可以打开“会话”窗口,如图3-24所示。
图3-24 “会话”窗口
“会话”窗口的“状态”列中,给出了会话的状态,可有如下几种状态。
● 正在启动:程序正在启动。不能对应用程序进行暂停、恢复或单步执行。
● 运行:被调试的应用程序已经启动,并正在执行指令。
● 已停止:因为遇到断点、已将应用程序暂停或执行了步骤命令(步入、越过、步出或运行至光标处),所以应用程序暂停。
3.7.5 “源”窗口
“源”窗口中列出了调试器可能会使用的源代码文件。选择“窗口”→“调试”→“源”命令,可以打开“源”窗口,如图3-25所示。
图3-25 “源”窗口
“源”窗口中的“用于调试”列中列出了哪些源代码是用于调试的,哪些不是。可以通过单击该列来修改这些属性。
3.8 小结
调试技术是程序开发中必不可少的技术,可以帮助开发人员迅速找到问题。由于在后续章节的学习中,都有可能进行代码调试,因此提前进行介绍。
本章介绍了在NetBeans中的调试技术,主要包括调试会话中各个调试窗口的使用方法。通过本章的学习,应该掌握如下的内容:
● 断点的类型以及断点的设置和管理方法
● 如何进行单步跟踪程序
● 如何查看变量和表达式的值