admin 管理员组

文章数量: 887172


2024年1月16日发(作者:命令执行漏洞工具)

4.4 在Eclipse中进行调试(1)

4.4 在Eclipse中进行调试

Eclipse为调试运行中的Java应用程序提供了完善的环境。当在主机模式下运行GWT应用程序时,Eclipse会将它作为一个Java应用程序来运行,而且开发者可以在Eclipse中调试这个GWT应用程序。对于Ajax开发过程来说,能够调试基于浏览器的Web应用程序的确是一种巨大的进步。

本章前面,我们看到使用applicationCreator脚本和-eclipse选项来创建应用程序时,会自动地创建一个Eclipse启动配置文件。然后,通过Eclipse就能在主机模式下用Run或Debug命令来启动该应用程序。启动以后,主机模式浏览器仍然与Eclipse保持连通,并且能够使用Eclipse的调试命令。

首先,我们从断点讲起。断点是指在代码中设置的一个位置,当执行到该位置时,应用程序会中断运行并将控制权转交给调试器。这样,我们就能够观察变量的状态或者逐行地执行代码以便于分析程序流。为了示范断点的应用,可以在HelloWorld应用程序中按钮的k方法的第一个行添加一个断点。设置方法是在编辑器中该行的左侧边空区域单击右键,选择Toggle Breakpoint,如图4-24所示。

图4-24 设置断点

这时,我们能够在左侧边空区域上看到由一个蓝色圆点图标表示的断点。而通过在该边空区域上双击同一个点可以切换断点。现在,当调试应用程序时,Eclipse会在程序执行到断点时接管调节器。对于HelloWorld这个例子而言,就是在单击按钮的时候程序会发生中断。下面,单击工具栏上的Bug图标,打开Debug菜单,从中选择HelloWorld,如图4-25所示。

图4-25 启动调试器

当在主机模式浏览器中打开HelloWorld时,单击Click Me按钮,就能够看到Eclipse显示的调试器。此时,应该看到Eclipse处于Debug透视图模式,如图4-26所示。

假如你打算构建像样的Ajax应用程序,那么就应该学会使用这个视图。在这个视图中,能够看到应用程序运行时的各个方面。如果应用程序运行出现了问题,那么可以通过设置断点来查找原因。JavaScript开发者可能会对这种调试工具感到比较陌生,因为它看起来似乎很复杂。然而,因为这个工具能够节省大量查找错误的时间,所以掌握它的使用是非常有必要的。同过去要打印和分析日志相比,在这里只需设置几个断点然后单步调试,甚至每次只执行一行代码,与此同时可以检查变量的值并确定错误所在。

下面介绍Debug透视图中的一些工具。首先,看一看Debug窗格上方的一排按钮。其中,绿色的箭头和红色的方块分别表示Resume(继续)和Terminate(终止)。单击Resume可以继续执行程序。在图4-26中,程序在断点处停止了执行。而单击Terminate按钮则会终止调试会话。一般来说,我们都通过关闭主机模式浏览器的窗口来结束程序。但在断点模式下,应用程序处于停止状态,因而无法访问主机模式浏览器的界面。

此时,结束程序的唯一方法就是使用Terminate按钮。在Resume和Terminate按钮旁边的黄色箭头,用于单步调试应用程序。当应用程序停止在一个断点处时,可以一步一步地执行代码。这样,开发者就能够看到执行每一步代码对变量所产生的影响。从另一个角度来说,这相当于延长了程序的执行时间,从而使开发者能够通过“慢镜头”来观察程序的执行流。第一个步进按钮是Step Into,单击该按钮会调用当前行的下一个方法。一般来说,这会导致执行流转移到另一个方法中,同时在堆栈中添加一行。当希望程序的执行流进入一个方法时,可以使用这个按钮。

如果不想进入另一个方法,可以使用下一个步进按钮Step Over,这个按钮用于执行当前代码行、调用任何方法并停止在当前方法中的下一行。第三个黄色的按钮是Step Return,它用来执行当前方法中其他的代码并返回调用方法,然后停止。

图4-26 Eclipse中的调试透视图

4.4 在Eclipse中进行调试(2)

在调试控件的下方是调用堆栈 。事实上,这就是一个Java应用程序中线程的树形列表,而相应的堆栈则是这个列表中的子项目。只有当线程停止在一个断点处时,才会出现这些堆栈。Ajax应用程序是单线程的,因此我们只需关注其中的一个线程和相应的堆栈即可。当解释程序在onClick方法中遇到断点时,单个JavaScript线程会显示出它的方法调用堆栈,而当前方法被突出显示。通过这个堆栈窗格,能够很方便地看出某个方法是在何时以及何处被调用的。通过单击其他方法,可以在编辑器中查看它们的代码。当以这种方式浏览堆栈时,Debug透视图会自动调整以反映堆栈中当前选中的行。例如,编辑器会显示选中方法中调用子方法的那行代码。当然,变量浏览器视图也会相应调整,以便展示与当前选中方法相关的变量。

变量视图中会列出当前方法使用的局部以及在用变量。视图中的列表是一个分栏的树形结构,从中可以看到每个变量的内容以及该变量是不是对象,同时在第二栏中显示它的值。视图的底部区域会显示对当前选中变量调用其toString方法后返回的文本。

有时,只通过断点和单步调试仍然无法找到和修改应用程序中的问题。例如,存在一个发生时间无法预测的异常,而设置的断点有可能导致异常发生前调试器会中断几千次。这种情形显然无法令人满意。所幸的是,Eclipse提供了一种当

特定的异常发生时进入调试器的方式。如果想添加一个异常断点,可以选择Run > Add Java Exception Breakpoint,这样会打开如图4-27所示的对话框。

图4-27 添加一个异常断点

在这个对话框中,可以选择想要中止的异常。其中的列表会随着输入文本而执行动态筛选操作。图4-27展示了要基于Java的ArrayIndexOutOfBoundsException中止的情形。单击OK之后,就能够在Debug透视图的Breakpoints视图中看到这个新添加的断点,如图4-28所示。

图4-28 Eclipse中的断点视图

要测试这一点,我们可以编写几行会导致索引越界的代码:

public void onModuleLoad() {

int[] ints = new int[1000];

for( int i = 0; i<=1000; i++ ){

ints[i] = i;

}

然后,在Debug模式下运行这个应用程序,Eclipse会在代码试图向数组中写入第1001个整数时中断(假如在这个测试过程中你还遇到了其他的越界异常,可以单击Resume按钮)。图4-29显示了停止在异常断点处的Debug透视图。

图4-29 当异常发生时进入调试器

可以看到,编辑器中的当前行正是导致越界异常的那一行。此时变量浏览器中显示的i的值为1000(数组从0开始,因此索引为1000的元素就是第1001个元素,而超过1000就算是越界)。这种断点的好处在于,开发者无需为找到问题所在而反复单调试1000次。当然,这个例子的价值是有限的,不过同样的技术也可以应用到具有类似行为的复杂例子中。

在知道HelloWorld中存在一个bug的前提下,我们还可以使用Eclipse的另一个优秀特性,该特性能够实时地更新代码并无需重启而继续执行应用程序。当应用程序停止在异常断点处时,可以对代码进行修改,如图4-30所示。

图4-30 在调试期间修改代码

图中的文字:

Changed <=1000 to < :把<=1000修改为<>

这里,我们把比较操作符设置为小于而不是小于等于,并且删除了1000而代之以数组的length属性。保存文件,继续执行应用程序,然后再在主机模式浏览器中单击Refresh按钮。你会发现应用程序运行的是修改后的代码,而且不会出现异常。这种技术可以节约相当多的时间,否则就得重启主机模式浏览器。而且,减少中断工作流的次数,也有助于开发者将思路集中在解决当前的问题上。


本文标签: 应用程序 方法 断点 执行 代码