JDB - 快速指南
JDB - Introduction
调试是一种技术过程,用于查找和删除程序中的错误或缺陷并获得预期结果。 调试包括测试和监控。 当程序的子单元紧密耦合时,它非常复杂。 我们可以使用遵循规定API的调试工具来调试程序。 调试器允许您逐步执行代码的每个方面,检查所有元素,并删除错误(如果有)。
调试技术
调试Java程序有不同的技术。 旧的调试方法是在每个段的末尾使用print语句,它将在控制台上打印trace语句。 看看下面的代码。
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);
}
}
在这里,我们有一个程序,它添加两个数字并打印输出。 请注意,在每一步中,我们都引入了一个print语句,用于在控制台上打印程序的状态。 这是调试程序的传统方法。
此外,我们还有可用于调试程序的高级概念,例如:
- stepping
- breakpoints, and
- exceptions or watchpoints.
调试类型
我们可以使用各种方法调试程序:
- 使用Java字节码(Java代码的编译版本)
- 在程序中使用注释
- 将类附加到正在运行的程序
- 远程调试
- 按需调试
- 优化的代码调试
Java调试器
以下是市场上可用的Java调试器的一些示例:
- Eclipse,Netbeans等IDE包含自己的调试器(Visual cafe,Borland,JBuilder)
- 独立调试器GUI(例如Jikes,Java平台调试器和JProbe)
- 命令行调试器(Sun的JDB)
- 记事本或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 - Installation
本章介绍如何在基于Windows和Linux的系统上安装JDB。 JDB是JDK的一部分。 因此,JDK安装足以在命令提示符中使用JDB。
系统需求 (System Requirements)
以下是安装JDB的系统要求:
JDK | Java SE 2 JDK 1.5或以上版本 |
Memory | 1 GB RAM(推荐) |
磁盘空间 | 没有最低要求 |
操作系统版本 | Windows XP或更高版本,Linux |
按照下面给出的简单步骤在您的系统上安装JDB。
第1步:验证Java安装
首先,您需要在系统上安装Java软件开发工具包(SDK)。 要验证这一点,请根据您正在使用的平台执行这两个命令中的任何一个。
如果Java安装已正确完成,则会显示Java安装的当前版本和规范。 下表给出了示例输出。
平台 | 命令 | 样本输出 |
---|---|---|
Windows | 打开命令控制台并键入: \》java –version | Java版“1.7.0_60” Java(TM)SE运行时环境(版本1.7.0_60-b19) Java Hotspot(TM)64位服务器VM(内置24.60-b09,混合模式) |
Linux | 打开命令终端并输入: $java –version | java版“1.7.0_25” 打开JDK运行时环境(rhel-2.3.10.4.el6_4-x86_64) 打开JDK 64位服务器VM(内置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 - Syntax
本章介绍JDB命令的语法。 语法包含四个部分,如下所示:
- JDB
- option
- class
- arguments
语法 (Syntax)
JDB的语法如下。
jdb [ options ] [ class ] [ arguments ]
JDB
它从Java Development Kit调用jdb.exe。
选项 (Options)
其中包括用于以高效方式调试Java程序的命令行选项。 JDB启动程序接受所有选项(例如-D,-classpath和-X)以及一些其他高级选项,例如(-attach,-listen,-launch等)。
Class
它是您要在其上执行调试操作的类名。
参数 (Arguments)
这些是在运行时为程序提供的输入值。 例如,arg [0],arg [1]到main()方法。
在上述四个部分中,选项是最重要的部分。
JDB - Options
本章介绍了JDB中可用的重要选项,这些选项是作为jdb命令的参数提交的。
选项 (Options)
下表包含JDB接受的选项列表:
名称 | 描述 |
---|---|
-help | 显示帮助消息并列出相关选项。 |
-sourcepath | 如果未指定path,则使用给定的源文件路径,然后使用默认路径“。”,即当前目录。 |
-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虚拟机。 |
Using Options with Commands
以下命令显示如何使用以上某些选项:
-help
以下命令使用JDB获取-help。
\>jdb -help
-attach
以下命令将调试器附加到指定的VM(端口号:1099)。
\> jdb -attach 1099
-listen
以下命令使当前VM上运行的JDB进程使用标准连接器(8008中的VM)进行等待。
\>jdb -listen 8088
-listenany
以下命令使当前VM上运行的JDB进程使用任何连接器(当前正在运行的端口中的VM)进行等待。
\>jdb –listenany
-tclient
以下命令在Java Hotspot(TM)VM(客户端)中执行应用程序。
\>jdb –tclient
-tserver
以下命令在Java Hotspot(™)VM(服务器)中执行应用程序。
\>jdb -tserver
JDB - Session
本章介绍如何以不同方式启动JDB会话。 JDB启动是启动JDB会话的常用技术。
启动JDB会话有两种不同的方法:
- 通过向其添加类(主类名)来启动JDB会话。
- 将JDB添加到运行JVM以启动会话。
通过添加类启动会话
以下命令启动JDB会话:
语法 (Syntax)
\>jdb <classname>
例子 (Example)
我们假设我们有一个名为TestClass的类。 以下命令从TestClass启动JDB会话。
\>jdb TestClass
如果您遵循此命令,它将启动具有任何指定参数的新Java VM。 此后,它会加载该类并在执行该类的第一个语句之前将其停止。
通过将JDB添加到正在运行的JVM来启动会话
下面给出了通过将JDB添加到正在运行的JVM来启动JDB会话的语法和示例。
语法 (Syntax)
以下语法适用于JDB会话:
-agentlib:jdwp=transport=dt_shmem,address=<add>,server=y,suspend=n
</add>
例子 (Example)
让我们假设主类名是TestClass ,JVM允许JDB稍后连接它。 以下是将JDB添加到JVM的命令:
\>java
-agentlib:jdwp=transport=dt_shmem,address=jdbconn,server=y,suspend=n TestClass
现在,您可以使用以下命令将JDB附加到JVM:
\> jdb -attach jdbconn
Note:这里, TestClass没有添加到JDB命令中,因为JDB连接到正在运行的VM而不是启动新的VM。
JDB - Basic Commands
本章将向您介绍JDB的基本命令。 启动会话后,这些命令用于调试程序。
以下是用于调试的命令列表。
名称 | 描述 |
---|---|
help or ? | 最重要的JDB命令; 它会显示一个包含简要说明的已识别命令列表。 |
run | 启动JDB并设置必要的断点后,可以使用此命令开始执行并调试应用程序。 |
cont | 在断点,异常或步骤之后继续执行已调试的应用程序。 |
显示Java对象和原始值。 | |
dump | 对于原始值,此命令与print相同。 对于对象,它会打印对象中定义的每个字段的当前值。 包括静态和实例字段。 |
threads | 列出当前正在运行的线程。 |
thread | 选择一个线程作为当前线程。 |
where | 转储当前线程的堆栈。 |
例子 (Example)
让我们假设我们有一个名为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 - Breakpoints
本章介绍断点的概念以及如何在程序中设置断点。 断点在调试时在特定代码行执行程序时引入显式停止或暂停。 在执行程序中获取有关程序中变量的知识非常有用。
语法 (Syntax)
以下命令在特定行号处设置断点:
> stop at <class name>:<Line no>
以下命令在特定方法或特定变量上设置断点:
> stop in <class name>:< Method name | Variable name>
例子 (Example)
以下示例显示如何在类中设置断点。
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
调试(Debugging)
让我们举一个调试的例子。 在这里,我们通过在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 - Stepping
本章介绍如何在调试程序时使用Stepping的概念。 步进是调试器功能,允许您逐行逐步执行代码。 使用此方法,您可以检查代码的每一行,以确保它们按预期运行。
在步进过程中使用以下命令:
- 步骤:执行下一行的步骤
- list:检查您在代码中的位置
- cont:继续剩下的执行
例子 (Example)
以下示例使用我们在上一章中使用的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
踏入
使用此命令,您可以单步执行代码的下一行。 如果代码的下一行是函数调用,则它通过驱动函数顶行的控件进入函数。
在以下代码中,箭头标记定义代码中的控制器。
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)因此控制器移动到加法函数的最顶行,带有箭头标记,如下所示:
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也执行下一行。 但是如果下一行是函数调用,它会在后台执行该函数并返回结果。
让我们举个例子。 在以下代码中,箭头标记定义代码中的控件。
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执行下一行。 如果下一行是一个函数调用,它会跳过该函数,并继续执行代码的其余行。
让我们举个例子。 在以下代码中,箭头标记定义代码中的控制器。
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 - Exception
本章介绍如何使用JDB处理异常类。 通常,只要程序在没有catch语句的情况下引发异常,VM就会打印异常行,异常原因并退出。 如果使用catch语句引发了异常,则异常由catch语句处理。 这里,VM打印输出以及异常原因。
当引发异常的类在JDB下运行时,它也会抛出uncaught异常。 可以使用catch命令处理该异常。
例子 (Example)
让我们举个类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 - In Eclipse
本章介绍如何在Eclipse中使用JDB。 在继续之前,您需要安装Eclipse Indigo。 按照下面给出的步骤在您的系统上安装Eclipse Indigo。
第1步:下载并安装Eclipse
您可以从以下链接下载Eclipse: http://www.eclipse.org/downloads/packages/eclipse-ide-java-ee-developers/indigosr2 : http://www.eclipse.org/downloads/packages/eclipse-ide-java-ee-developers/indigosr2
第2步:创建一个新项目和一个新类
- 按照File-> New -> Java project选项创建一个新的File-> New -> Java project 。
- 将其命名为“sampledebug” 。
- 右键单击samplebebug项目创建一个新类。
- 选择options ->new -> class
- 将其命名为“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步:打开Debug Perspective
按照下面给出的说明打开调试透视图。
在Eclipse IDE上,转到Window -》 Open perspective -》 Debug 。 现在,您将获得Add.java程序的调试透视图。 您将看到以下窗口。
Debug Perspective中的部分
Debug透视图中的部分如下:
编码部分
Java代码显示在此部分中。 它是您要调试的代码,即Add.java 。 在这里,我们可以通过在线前面双击来在线上添加断点。 您会发现带有箭头符号的蓝色气泡指出该线的断点。 请参阅以下屏幕截图; 您可以找到所选区域,红色圆圈指向“1”。
- 双击这里。 您可以设置此行的断点。
断点部分
此部分定义设置为程序代码的断点列表。 在这里,我们可以添加,删除,查找和管理断点。 以下屏幕截图显示了断点部分。
观察给定屏幕截图中的以下选项:
使用左侧的复选框,我们可以选择或取消选择断点。 这里,我们使用一个断点,即Add class-main()方法。
单个十字图标“X”用于删除选定的断点。
双十字图标“XX”用于删除代码中的所有断点。
箭头指针用于指向应用所选断点的代码。
断点部分的其余功能如下:
Hitcount :它显示控件击中此断点的次数。 它用于递归逻辑。
Suspend thread :我们可以通过选择挂起当前线程。
Suspend VM :我们可以通过选择它来暂停VM。
调试部分
本节用于调试过程。 它包含调试中使用的选项。
Start debugging :按照下面的说明开始调试。
右键单击code -》单击Debug as -》单击1 Java application 。
调试过程如下面的屏幕截图所示。 它包含一些选定的选项,使用数字突出显示。
我们在Add class main()方法上应用断点。 当我们开始调试时, controller卡在main()方法的第一行。
它用于Resume调试过程并跳过当前断点。 它的工作方式类似于JDB命令行中的cont命令。
它用于停止调试过程。
它的工作方式类似于JDB命令行中的step in 。 它用于将控件移动到下一行,即点“1”移动到下一行。
它的工作方式类似于JDB命令行中的step over过程。
它用于查看应用断点的行。
按照给定的步骤和部分在eclipse IDE中调试代码。 默认情况下,每个IDE都包含此调试过程。