- JDB 教程
- JDB - 首页
- JDB - 简介
- JDB - 安装
- JDB - 语法
- JDB - 选项
- JDB - 会话
- JDB - 基本命令
- JDB - 断点
- JDB - 单步执行
- JDB - 异常
- JDB - 在 Eclipse 中
- JDB 有用资源
- JDB 快速指南
- JDB - 有用资源
- JDB - 讨论
JDB 快速指南
JDB - 简介
调试是一个技术过程,用于查找并移除程序中的错误或缺陷,并获得预期的结果。调试包括测试和监控。当程序的子单元紧密耦合时,调试会变得非常复杂。我们可以使用遵循规定的 API 的调试器工具来调试程序。调试器允许您逐步浏览代码的每个方面,检查所有元素,并消除任何错误。
调试技术
有不同类型的技术可以用来调试 Java 程序。旧的调试方法是使用打印语句在每个段的末尾,这将在控制台上打印跟踪语句。请查看以下代码。
pubic class Add { public static void main(String ar[]) { int a=ar[0]; system.out.println("A : " +a); int b=ar[1]; system.out.println("B : " +b); int c = a + b; system.out.println("C = a + b : " +c); } }
这里,我们有一个程序,它将两个数字相加并打印输出。请注意,在每个步骤中,我们都引入了一个打印语句,该语句在控制台上打印程序的状态。这是调试程序的传统方法。
此外,我们还有可以用来调试程序的高级概念,例如
- 单步执行
- 断点,以及
- 异常或监视点。
调试类型
我们可以使用多种方法调试程序
- 使用 Java 字节码(Java 代码的编译版本)
- 在程序内部使用注释
- 将类附加到正在运行的程序
- 远程调试
- 按需调试
- 优化代码调试
Java 调试器
以下是一些市面上可用的 Java 调试器的示例
- IDE(如 Eclipse、Netbeans 等)包含它们自己的调试器(Visual cafe、Borland、JBuilder)
- 独立调试器 GUI(如 Jikes、Java 平台调试器和 JProbe)
- 命令行调试器(Sun 的 JDB)
- Notepad 或 VI 驱动(堆栈跟踪)
本教程介绍如何使用命令行调试器jdb。
JDB
Java 调试器 (JDB) 是一个用于 Java 类的工具,用于在命令行中调试程序。它实现了 Java 平台调试器架构。它有助于使用 Java 调试接口 (JDI) 检测和修复 Java 程序中的错误。
JDK 中的 JDB
以下架构定义了 JDB 在 JDK 中的角色。它主要包含三个单元
- Java 虚拟机工具接口 (JVM TI)
- Java 调试线池 (JDWP)
- Java 调试接口 (JDI)
JVM TI
它是由 VM 实现的本机编程接口。它提供了检查和调试在 VM 上运行的应用程序状态的方法。它允许实现者(VM 实现者)可以轻松地封装到调试架构中。它还使用名为JDWP的第三方通道进行通信。
JDWP
它定义了在被调试进程和调试器前端之间传递的信息和请求的格式。拥有 JDWP 的主要目的是允许被调试器和调试器在它们在单独的 VM 或单独的平台上运行时进行通信。
JDI
它是一个作为前端实现的高级 Java 接口。它定义了用户代码级别上的变量信息。建议对所有调试器开发使用 JDI 层。它使用 JDWP 与被调试的 JVM 通信。
JDB - 安装
本章说明如何在基于 Windows 和 Linux 的系统上安装 JDB。JDB 是 JDK 的一部分。因此,JDK 安装足以在命令提示符下使用 JDB。
系统要求
以下是安装 JDB 的系统要求
JDK | Java SE 2 JDK 1.5 或更高版本 |
内存 | 1 GB RAM(推荐) |
磁盘空间 | 无最低要求 |
操作系统版本 | Windows XP 或更高版本,Linux |
按照以下给出的简单步骤在您的系统上安装 JDB。
步骤 1:验证 Java 安装
首先,您需要在您的系统上安装 Java 软件开发工具包 (SDK)。要验证这一点,请根据您正在使用的平台执行以下两个命令中的任何一个。
如果 Java 安装已正确完成,则它会显示 Java 安装的当前版本和规范。示例输出在以下表格中给出。
平台 | 命令 | 示例输出 |
---|---|---|
Windows |
打开命令控制台并键入 \>java –version |
Java 版本 "1.7.0_60" Java (TM) SE 运行时环境 (build 1.7.0_60-b19) Java Hotspot (TM) 64 位服务器 VM (build 24.60-b09,混合模式) |
Linux |
打开命令终端并键入 $java –version |
java 版本 "1.7.0_25" Open JDK 运行时环境 (rhel-2.3.10.4.el6_4-x86_64) Open JDK 64 位服务器 VM (build 23.7-b01,混合模式) |
我们假设本教程的读者在其系统上安装了 Java SDK 版本 1.7.0_60。如果您没有 Java SDK,请从链接http://www.oracle.com/technetwork/java/javase/downloads/index.html下载其当前版本并安装它。
步骤 2:设置 Java 环境
设置环境变量 JAVA_HOME 以指向 Java 安装在您计算机上的基本目录位置。例如,
平台 | 描述 |
---|---|
Windows | 将 JAVA_HOME 设置为 C:\ProgramFiles\java\jdk1.7.0_60 |
Linux | export JAVA_HOME=/usr/local/java |
将 Java 编译器位置的完整路径附加到系统路径。
平台 | 描述 |
---|---|
Windows | 在系统变量 PATH 的末尾附加字符串 "C:\Program Files\Java\jdk1.7.0_60\bin"。 |
Linux | export PATH=$PATH:$JAVA_HOME/bin/ |
从命令提示符执行命令java -version,如上所述。
步骤 3:验证 JDB 安装
如下验证 JDB 版本
平台 | 命令 | 示例输出 |
---|---|---|
Windows |
打开命令控制台并键入 \>jdb –version |
这是 JDB 版本 1.6(Java SE 版本 1.7.0_60) |
Linux |
打开命令终端并键入 $jdb –version |
这是 JDB 版本 1.6(Java SE 版本 1.7.0_60) |
JDB - 语法
本章解释了 JDB 命令的语法。语法包含以下列出的四个部分
- JDB
- 选项
- 类
- 参数
语法
JDB 的语法如下。
jdb [ options ] [ class ] [ arguments ]
JDB
它从 Java 开发工具包调用 jdb.exe。
选项
这些包括用于以有效方式调试 Java 程序的命令行选项。JDB 启动器接受所有选项(例如 -D、-classpath 和 -X)以及一些其他高级选项(例如 (-attach、-listen、-launch 等)。
类
它是您要对其执行调试操作的类名。
参数
这些是在运行时给定给程序的输入值。例如,arg[0]、arg[1] 到 main() 方法。
在以上四个部分中,选项是最重要的一个。
JDB - 选项
本章描述了 JDB 中可用的重要选项,这些选项作为参数与 jdb 命令一起提交。
选项
下表包含 JDB 接受的选项列表
名称 | 描述 |
---|---|
-help | 显示帮助消息并列出相关选项。 |
-sourcepath | 如果未指定路径,则使用给定路径作为源文件,否则它将采用默认路径“.”,即当前目录。 |
-attach | 通过指定正在运行的 VM 地址将调试器附加到正在运行的 VM。 |
-listen | 等待正在运行的 VM 使用标准连接器连接。 |
-listenany | 等待正在运行的 VM 使用任何地址连接。 |
-launch | 在启动作业时立即启动被调试的应用程序。 |
-listconnectors | 列出此 VM 中可用的连接器。 |
-connect | 使用命名连接器和列出的参数值连接到目标 VM。 |
-dbgtrace | 打印用于调试 jdb 的信息。 |
-tclient | 在 Java Hotspot VM(客户端)中运行应用程序。 |
-tserver | 在 Java Hotspot VM(服务器)中运行应用程序。 |
-Joption | 将选项传递给用于运行 JDB 的 Java 虚拟机。 |
将选项与命令一起使用
以下命令显示如何使用上述一些选项
-help
以下命令获取有关使用 JDB 的 -help。
\>jdb -help
-attach
以下命令将调试器附加到指定的 VM(端口号:1099)。
\> jdb -attach 1099
-listen
以下命令使 JDB 进程在当前 VM 上使用标准连接器等待(VM 在 8008)。
\>jdb -listen 8088
-listenany
以下命令使 JDB 进程在当前 VM 上使用任何连接器等待(VM 在当前运行的端口)。
\>jdb –listenany
-tclient
以下命令在 Java Hotspot(™) VM(客户端)中执行应用程序。
\>jdb –tclient
-tserver
以下命令在 Java Hotspot(™) VM(服务器)中执行应用程序。
\>jdb -tserver
JDB - 会话
本章介绍如何以不同的方式启动 JDB 会话。JDB 启动是启动 JDB 会话的常用技术。
有两种不同的方法可以启动 JDB 会话
- 通过向其中添加类(主类名)来启动 JDB 会话。
- 将 JDB 添加到正在运行的 JVM 以启动会话。
通过添加类启动会话
以下命令启动 JDB 会话
语法
\>jdb <classname>
示例
假设我们有一个名为TestClass的类。以下命令从 TestClass 启动 JDB 会话。
\>jdb TestClass
如果您遵循此命令,它将使用任何指定的参数启动一个新的 Java VM。然后它加载类并在执行类的第一个语句之前停止它。
通过将 JDB 添加到正在运行的 JVM 启动会话
下面是通过将 JDB 添加到正在运行的 JVM 启动 JDB 会话的语法和示例。
语法
以下语法适用于 JDB 会话
-agentlib:jdwp=transport=dt_shmem,address=,server=y,suspend=n
示例
假设主类名是TestClass,并且 JVM 允许 JDB 稍后连接它。以下是将 JDB 添加到 JVM 的命令
\>java -agentlib:jdwp=transport=dt_shmem,address=jdbconn,server=y,suspend=n TestClass
现在您可以使用以下命令将 JDB 附加到 JVM
\> jdb -attach jdbconn
注意:此处,TestClass未添加到 JDB 命令中,因为 JDB 连接到正在运行的 VM 而不是启动一个新的 VM。
JDB - 基本命令
本章将引导您了解 JDB 的基本命令。启动会话后,这些命令用于调试程序。
以下是用于调试的命令列表。
名称 | 描述 |
---|---|
help 或 ? | 最重要的JDB命令;它显示已识别命令的列表以及简要说明。 |
run | 在启动JDB并设置必要的断点后,您可以使用此命令启动执行并调试应用程序。 |
cont | 在断点、异常或单步执行后继续执行调试的应用程序。 |
显示 Java 对象和基本值。 | |
dump | 对于基本值,此命令与 print 相同。对于对象,它会打印对象中定义的每个字段的当前值。包括静态和实例字段。 |
threads | 列出当前正在运行的线程。 |
thread | 选择一个线程作为当前线程。 |
where | 转储当前线程的堆栈。 |
示例
让我们假设对于以下示例,我们有一个名为**Add**的示例类
Add.java
public class Add { public int addition( int x, int y) { int z = x+y; return z; } public static void main( String ar[ ] ) { int a = 5, b = 6; Add ob = new Add(); int c = ob.addition(a,b); System.out.println("Add: "+c); } }
使用以下命令编译此类 Add.java
\>javac Add.java
Run
此命令执行主类文件,该文件已添加到 JDB 以进行调试。执行以下命令以运行 Add 类。
\>jdb Add initializing jdb … >run
执行这些命令后,您将看到以下输出
JDB - 断点
本章介绍断点的概念以及如何在程序中设置断点。断点在调试期间会在程序执行的特定代码行处引入显式停止或暂停。它有助于在程序执行过程中获取有关程序中变量的知识。
语法
以下命令在特定行号处设置断点
> stop at <class name>:<Line no>
以下命令在特定方法或特定变量上设置断点
> stop in <class name>:< Method name | Variable name>
示例
以下示例演示如何在类中设置断点。
public class Add { public int addition( int x, int y) { int z = x+y; return z; } public static void main( String ar[ ] ) { int a = 5, b = 6; Add ob = new Add(); int c = ob.addition(a,b); System.out.println("Add: "+c); } }
将以上文件保存为 Add.java。使用以下命令编译此文件
\>javac Add.java
调试
让我们以调试为例。在这里,我们通过在 main() 上设置断点来启动调试过程。以下是调试过程中需要遵循的步骤
步骤 1:启动 JDB 会话
以下命令在 Add 类上启动 JDB 会话以进行调试
\> jdb Add
步骤 2:设置断点
以下命令在 Add 类的 main() 方法上设置断点。
> stop in Add.main
如果断点设置成功,您将看到以下输出
Deferring breakpoint Add.main. It will set after the class is loaded. >
步骤 3:开始调试
以下命令开始执行类 Add
> run Add
如果运行此命令,您将看到以下输出。在此输出中,您会发现执行在断点位置停止,即在 main() 函数处。
执行在 main 方法的第一行停止,即在“int a=5, b=6;”或代码中的第 11 行。您可以在输出中观察到此信息。
步骤 4:继续执行
以下命令继续程序执行
cont
它为您提供其余的执行部分和输出,如下所示
> Add:11 The application exited \>
JDB - 单步执行
本章介绍如何在调试程序中使用单步执行的概念。单步执行是调试器功能,允许您逐行执行代码。使用此功能,您可以检查代码的每一行以确保它们按预期运行。
以下命令用于单步执行过程
- step:单步执行到下一行
- list:检查您在代码中的位置
- cont:继续执行剩余部分
示例
以下示例使用我们在上一章中使用的 Add 类
public class Add { public int addition( int x, int y) { int z = x+y; return z; } public static void main( String ar[ ] ) { int a = 5, b = 6; Add ob = new Add(); int c = ob.addition(a,b); System.out.println("Add: "+c); } }
将以上文件保存为 Add.java。使用以下命令编译此文件
\>javac Add.java
让我们假设断点已设置在 Add 类的 main() 方法上。以下步骤演示如何在 Add 类中应用单步执行。
步骤 1:执行作业
以下命令开始执行名为 Add 的类。
> run Add
如果执行此命令,您将看到以下输出。在此输出中,您可以发现执行在断点位置停止,即在 main() 方法处。
执行在 main 方法的第一行停止,即在“int a=5, b=6;”或代码中的第 11 行。您可以在输出中观察到此信息。
步骤 2:单步执行代码
以下命令将执行单步执行到下一行。
main[1] step
现在执行单步执行到第 12 行。您将看到以下输出。
步骤 3:列出代码
以下命令列出代码
main[1] list
您将获得以下输出。list 命令用于让您知道程序控制已到达的代码行。请注意以下屏幕截图中的箭头标记=>,它显示了程序控制的当前位置。
步骤 4:继续执行
以下命令继续执行代码
main[1] cont
此命令继续执行代码的其余行。输出如下所示
> Add:11 The application exited \>
通常,单步执行有三种类型
- Step Into(步入)
- Step Over(步过)
- Step Out(步出)
Step Into(步入)
使用此命令,您可以单步执行到代码的下一行。如果代码的下一行是函数调用,则它会通过将控制驱动到函数的顶行来进入该函数。
在以下代码中,箭头标记定义了代码中的控制器。
public class Add { public int addition( int x, int y) { int z = x+y; return z; } public static void main( String ar[ ] ) { int a = 5, b = 6; -> Add ob = new Add(); int c = ob.addition(a,b); System.out.println("Add: "+c); } }
如果使用**step into**命令,控制器将移动到下一行,即“int c = ob.addition(a,b);”。在此行中,有一个函数调用**addition(int, int)**,因此控制器将移动到 addition 函数的最顶行,箭头标记如下所示
public class Add { public int addition( int x, int y) -> { int z = x+y; return z; } public static void main( String ar[ ] ) { int a = 5, b = 6; Add ob = new Add(); int c = ob.addition(a,b); System.out.println("Add: "+c); } }
Step Over(步过)
Step Over 也执行下一行。但是,如果下一行是函数调用,它会在后台执行该函数并返回结果。
让我们举个例子。在以下代码中,箭头标记定义了代码中的控制。
public class Add { public int addition( int x, int y) { int z = x+y; return z; } public static void main( String ar[ ] ) { int a = 5, b = 6; -> Add ob = new Add(); int c = ob.addition(a,b); System.out.println("Add: "+c); } }
如果使用**step over**命令,控制器将移动到下一行,即“int c = ob.addition(a,b);”。在此行中,有一个函数调用**addition(int, int)**,因此函数执行在后台完成,结果将返回到当前行,箭头标记如下所示
public class Add { public int addition( int x, int y) { int z = x+y; return z; } public static void main( String ar[ ] ) { int a = 5, b = 6; Add ob = new Add(); -> int c = ob.addition(a,b); System.out.println("Add: "+c); } }
Step Out(步出)
Step Out 执行下一行。如果下一行是函数调用,它会跳过该调用,并且函数执行将继续执行代码的其余行。
让我们举个例子。在以下代码中,箭头标记定义了代码中的控制器。
public class Add { public int addition( int x, int y) { int z = x+y; return z; } public static void main( String ar[ ] ) { int a = 5, b = 6; -> Add ob = new Add(); int c = ob.addition(a,b); System.out.println("Add: "+c); } }
如果使用**step out**命令,控制器将移动到下一行,即“int c = ob.addition(a,b);”。在此行中,有一个函数调用**addition(int, int)**,因此函数执行被跳过,其余执行将继续执行,箭头标记如下所示
public class Add { public int addition( int x, int y) { int z = x+y; return z; } public static void main( String ar[ ] ) { int a = 5, b = 6; Add ob = new Add(); -> int c = ob.addition(a,b); System.out.println("Add: "+c); } }
JDB - 异常
本章介绍如何使用 JDB 处理异常类。通常,每当程序引发没有 catch 语句的异常时,VM 都会打印异常行、异常原因并退出。如果异常已使用 catch 语句引发,则异常将由 catch 语句处理。在这里,VM 会打印带有异常原因的输出。
当引发异常的类在 JDB 下运行时,它也会抛出**未捕获的**异常。可以使用**catch**命令处理该异常。
示例
让我们以 JdbException 类为例
public class JdbException { public static void main(String ar[]) throws Exception { int a=8, b=0; System.out.println("Welcome"); System.out.println("Ex: "+(a/b)); } }
将以上文件保存为 JdbException.java。使用以下命令编译此文件
\>javac JdbException.java
按照以下步骤处理异常。
步骤 1:运行类
以下命令执行名为**JdbException**的类,如下所示
\>jdb JdbException >run
此**JdbException**类包含异常,因此您将看到以下输出
步骤 2:捕获异常
以下命令捕获异常
mian[1] catch java.lang.ArithmeticException
它将为您提供以下输出
Set all java.lang.ArithmeticException
步骤 3:继续执行
以下命令继续执行。现在 catch 处理算术异常,如下所示
JDB - 在 Eclipse 中
本章介绍如何在 Eclipse 中使用 JDB。在继续之前,您需要安装 Eclipse Indigo。请按照以下步骤在您的系统上安装 Eclipse Indigo。
步骤 1:下载并安装 Eclipse
您可以从以下链接下载 Eclipse:http://www.eclipse.org/downloads/packages/eclipse-ide-java-ee-developers/indigosr2
步骤 2:创建新项目和新类
- 按照**文件 -> 新建 -> Java 项目**选项创建新的 Java 项目。
- 将其命名为**“sampledebug”**。
- 右键单击**samplebebug**项目创建新类。
- 选择**选项 -> 新建 -> 类**
- 将其命名为**“Add.java”**
Add.java
public class Add { public int addition( int x, int y) { int z = x+y; return z; } public static void main( String ar[ ] ) { int a = 5, b = 6; Add ob = new Add(); int c = ob.addition(a,b); System.out.println("Add: "+c); } }
步骤 3:打开调试透视图
按照以下说明打开调试透视图。
在 Eclipse IDE 上,转到**窗口 -> 打开透视图 -> 调试**。现在您将获得程序 Add.java 的调试透视图。您将看到以下窗口。
调试透视图中的部分
调试透视图中的部分如下所示
编码部分
此部分显示 Java 代码。这是您要调试的代码,即**Add.java**。在这里,我们可以通过双击代码行前面的位置在该行上添加断点。您会发现带有箭头符号的蓝色圆圈来指出该行的断点。请参阅以下屏幕截图;您可以找到用红色圆圈标记的选定区域“1”。
- 在此处双击。您可以为该行设置断点。
断点部分
此部分定义了设置为程序代码的断点列表。在这里,我们可以添加、删除、查找和管理断点。以下屏幕截图显示了断点部分。
观察给定屏幕截图中的以下选项
使用左侧的复选框,我们可以选择或取消选择断点。在这里,我们使用一个断点,即 Add 类-main() 方法。
单个叉子图标“X”用于删除选定的断点。
双叉子图标“XX”用于删除代码中的所有断点。
箭头指针用于指向应用选定断点的代码。
断点部分中的其余功能如下所示
命中次数:它显示控制到达此断点的次数。它用于递归逻辑。
挂起线程:我们可以通过选择它来挂起当前线程。
挂起 VM:我们可以通过选择它来挂起 VM。
调试部分
此部分用于调试过程。它包含调试中使用的选项。
开始调试:请按照以下说明开始调试。
右键单击代码 ->单击作为调试 ->单击1 Java 应用程序。
调试过程开始,如下面的屏幕截图所示。它包含一些选定的选项,使用数字突出显示。
我们在 Add 类 main() 方法上应用了断点。当我们开始调试时,控制器将停留在 main() 方法的第一行。
用于恢复调试过程并跳过当前断点。其工作方式类似于 JDB 命令行中的cont命令。
用于停止调试过程。
其工作方式类似于 JDB 命令行中的step in过程。用于将控制权移至下一行,即点“1”移至下一行。
其工作方式类似于 JDB 命令行中的step over过程。
用于查看断点应用在哪一行。
按照给定的步骤和部分在 eclipse IDE 中调试代码。默认情况下,每个 IDE 都包含此调试过程。