`

java调试原理

    博客分类:
  • java
阅读更多
引用

目前可以用来调试Java应用程序的工具令人叹为观止。现代ide提供了全功能的调试界面,并且像glassbox这样的工具用bci(bytecode instrumentation)提供了关于应用程序运行时状态的更多信息。虽然你有时候会发现自己处于无法使用这些工具的境地,或许应用程序被部署在防火墙的另一端,不允许你远程调试;或许你正在客户那里,没有你喜欢的工具可用。现代调试工具使用的大多数信息和方法都由jvm自己提供,并具有控制这种信息而不用最新图形工具的一些方法。本文关注一些可用的调试方法,它们只使用java sdk(jdk)自带的那些工具。

jdb i!\W^udUAX=n3kg`!p [ 本 资 料 来 源 于 贵 州 学 习 网 网络编程Java教程 http://Www.gzU521.com ] i!\W^udUAX=n3kg`!p

jdk携带的主要调试工具是jdb,这是一种命令行调试器,它将附到一个在运行的vm,并允许你设置断点(breakpoint)、逐步跟踪代码、检验变量并评估表达式的值。jre没有包括jdb,因此你需要安装jdk。

如果你知道如何利用ide中内建的任何调试器调试java应用程序,你就可以迅速地学会利用jdb进行调试。为了允许jdb或者任何调试器连接到一个在运行的jvm,jvm必须通过许多命令行参数来启动。这些参数促成jvm去加载和初始化调试库,配置传输并打开一个socket。例如,要配置vm在端口8000监听调试连接,你应该使用类似于下面的命令行选项:

-Xdebug -Xrunjdwp:transport=dt_socket,suspend=n,server=y,address=8000

你现在可以利用下面的命令行用jdb连接:

jdb -attach 8000

或者在windows上:

jdb -connect com.sun.jdi.SocketAttach:port=8000

一旦连接上,你应该看到jdb提示。

你现在连接到了jvm,可以开始调试你的应用程序了。你想要做的第一件事可能是设置一些断点。在jdb中设置断点有三种方法。

1、在命名方法的项上设置断点。
2、在指定的源代码行数上设置断点。
3、在发生特定异常的时候。

当你的应用程序触发断点时,jvm将中止执行,并等待你告诉它接下来要利用jdb做什么。你可以跳过去,进入到方法调用里面,检查本地变量,并评估表达式,为了获得一个可用命令的列表,可以输入help来得到它。

虽然利用jdb调试比用为你显示源代码行的图形调试器更慢,但是只要你访问源代码,就可以获得与利用jdb相同的效果。

不建议你通过调试参数运行产品应用程序,因为使用这些参数的时候,有一个性能和安全问题。但在测试、开发期间以及检查某类产品问题的时候,jdb都是一种非常有用的工具。

关于jdb的更多信息,请见sun的文档:http://java.sun.com/j2se/1.3/docs/tooldocs/win32/jdb.html。

利用thread dump

现代的java和jave ee应用程序有许多线程,它们全都彼此交互,并连接到外部系统。java提供了一种获取在vm中运行的所有线程的调用堆栈快照的方法。这个的输出称作 thread dump,它是大量的堆栈轨迹(每个线程一个),以及关于线程优先级和它持有或等待的任何锁或监视器的信息。

生成thread dump在不同的操作系统中做起来也不同。在windows中,是在jvm运行的控制台窗口中按下ctrl-break。对基于LINUX和unix的系统,则用kill命令将sigquit发送到jvm。这可以通过命令kill – 3 完成,这里的pid是jvm的进程id。

现代的企业java应用程序中,经常有大量的线程,它们中有许多都没起任何作用。你可以用许多种方式来辨别重要的线程。

◆它们通常具有较长的相关堆栈轨迹。
◆搜索已知的包名称(例如你应用程序中使用的包)。SCK&U@m RNRV2!"0m8'[ 此文转贴于我的学习网网络编程Java教程 http://www.Gzu521.com]SCK&U@m RNRV2!"0m8'

线程持有或者等待的任何锁或者监视器都在轨迹中指定,因此死锁以及其他同步相关的问题,都可以通过分析哪些线程在等待或者持有哪些锁和监视器进行辨别。

在性能调优或者调试慢运行应用程序时,它对相隔几秒钟生成许多thread dump并对它们进行比较会很有利。这样让你知道应用程序的哪些部分正在缓慢地运行着,而不必使用更高级的性能分析工具。

jmx

从java se 5开始,sun给jvm运行时信息提供了jmx api作为java se的一部分,sun还提供了一种工具,用来在一个正运行的jvm内部查询mbeans。这个工具是jconsole,并且就像jdb一样,它是与jdk捆绑在一起的。

为了允许jconsole连接到你的vm,你需要增加许多命令行参数。

-dcom.sun.management.jmxremote
-dcom.sun.management.jmxremote.port=20001
-dcom.sun.management.jmxremote.authenticate=false
-dcom.sun.management.jmxremote.ssl=false

当你运行jconsole时,它将在你的机器上侦测vm运行,并问你想要连接到哪一个。一旦你连接上了,摘要(summary)屏幕就会显示大量关于vm的信息,让你访问使用关于它线程的运行时信息、堆的使用(heap usage),以及所有变得能通过jmx mbeans使用的信息。通过将mbeans增加到你的应用程序中,有可能使你的应用程序信息能通过jmx控制台以及用jmx接口收集它们信息的其他工具来使用。利用jmx将监视功能增加到你的应用程序,则是另一篇文章的主题了。

关于使用jconsole的更多信息,请见:http://java.sun.com/j2se/1.5.0/docs/guide/management/jconsole.html。

信息唾手可得

这些工具虽然不完整,或者不像你习以为常的工具那么容易使用,但它们仍然提供了很多你可以用来分析和调试你应用程序的信息。基本熟悉了它们之后,就可以快速解决问题,否则要花数天进行调查,因此值得花时间去体验它们,并了解它们是如何工作的。

http://java.sun.com/j2ee/1.4/docs/devguide/dgdebug.html

http://docs.sun.com/source/819-0079/dgdebug.html

http://www.infoq.com/cn/articles/basic-java-debugging



-----------------------------------------------------------------------------

jdb -connect com.sun.jdi.SocketAttach:port=8000

stop in  com.soulinfo.webcomponent.ArchiveBorrow_Component.onInit
stop at  com.soulinfo.webcomponent.ArchiveBorrow_Component:154
clear com.soulinfo.webcomponent.ArchiveBorrow_Component.onInit
clear com.soulinfo.webcomponent.ArchiveBorrow_Component:154

run 继续执行
cont 继续执行
next ->执行一行(STEP)
step ->执行一行(STEP INTO)
locals -> 显示局部变量
dump 对象名  ->显示对象信息
print 对象名  ->显示简单对象信息

> help
** 命令列表 **
connectors                  - 列出此 VM 中可用的连接器和传送器

run [类 [参数]]             - 开始执行应用程序的主类

threads [线程组]            - 列出线程
thread <线程 ID>            - 设置默认线程
suspend [线程 ID]           - 暂停线程(默认为所有线程)
resume [线程 ID]            - 恢复线程(默认为所有线程)
其中 [<线程 ID> | all]      - 转储线程的堆栈
其中 [<线程 ID> | all]      - 转储线程的堆栈,以及 pc 信息
up [n 帧]                   - 向上移动线程的堆栈
down [n 帧]                 - 向下移动线程的堆栈
kill <线程 ID> <表达式>     - 中止具有给定的异常对象的线程
interrupt <线程 ID>         - 中断线程

print <表达式>              - 输出表达式的值
dump <表达式>               - 输出所有对象信息
eval <表达式>               - 输出表达式的值(与 print 相同)
set <lvalue> = <表达式>     - 为字段/变量/数组元素指定新值
locals                      - 输出当前堆栈帧中的所有局部变量

classes                     - 列出当前已知的类
class <类 ID>               - 显示已命名的类的详细信息
methods <类 ID>             - 列出类的方法
fields <类 ID>              - 列出类的字段

threadgroups                - 列出线程组
threadgroup <名称>          - 设置当前线程组

stop in <类 ID>.<方法>[(参数类型,...)]
                            - 在方法中设置断点
stop at <类 ID>:<行>        - 在行中设置断点
clear <类 ID>.<方法>[(参数类型,...)]
                            - 清除方法中的断点
clear <类 ID>:<行>          - 清除行中的断点
clear                       - 列出断点
catch [uncaught|caught|all] <类 ID>|<类模式>
                            - 出现指定的异常时中断
ignore [uncaught|caught|all] <类 ID>|<类模式>
                            -- 对于指定的异常,取消 "catch"
watch [access|all] <类 ID>.<字段名>
                            - 监视对字段的访问/修改
unwatch [access|all] <类 ID>.<字段名>
                            - 停止监视对字段的访问/修改
trace methods [线程]        - 跟踪方法输入和退出
untrace methods [线程]      - 停止跟踪方法输入和退出
step                        - 执行当前行
step up                     - 执行到当前方法返回到其调用程序
stepi                       - 执行当前指令
next                        - 跳过一行(跨过调用)
cont                        - 从断点处继续执行
list [line number|method]   - 输出源代码
use(或 sourcepath) [源文件路径]
                            - 显示或更改源路径
exclude [<类模式>, ...| “无”]
                            - 对于指定的类,不报告步骤或方法
classpath                   - 从目标 VM 输出类路径信息

monitor <命令>              - 每次程序停止时执行命令
monitor                     - 列出监视器
unmonitor <监视器号>        - 删除监视器
read <文件名>               - 读取并执行命令文件

lock <表达式>               - 输出对象的锁信息
threadlocks [线程 ID]       - 输出线程的锁信息

pop                         - 弹出整个堆栈,且包含当前帧
reenter                     - 与 pop 相同,但重新输入当前帧
redefine <类 ID> <类文件名>
                            - 重新定义类的代码

disablegc <表达式>          - 禁止对象的垃圾收集
enablegc <表达式>           - 允许对象的垃圾收集

!!                          - 重复执行最后一个命令
<n> <命令>                  - 将命令重复执行 n 次
help(或 ?)                - 列出命令
version                     - 输出版本信息
exit(或 quit)             - 退出调试器

<类 ID>:带有软件包限定符的完整类名
<类模式>:带有前导或后缀通配符 (*) 的类名
<线程 ID>: "threads" 命令中报告的线程号
<表达式>:Java(TM) 编程语言表达式。
支持大多数常见语法。

可以将启动命令置于 "jdb.ini" 或 ".jdbrc" 之中
(两者位于 user.home 或 user.dir 中)
>
分享到:
评论

相关推荐

    java进行远程部署与调试及原理详解

    远程调试原理 Java 远程调试的原理是基于 JVM 的调试机制。JVM 提供了一个简单的调试工具 JDB,支持设置断点和线程级的调试。不同的 JVM 通过接口的协议联系,本地的 Java 文件在远程 JVM 建立联系和通信。 ...

    Java调试体系及协议

    在使用Java调试时,了解JPDA的工作原理能够帮助开发者更有效地定位问题。例如,通过JDWP,开发者可以捕获到详细的线程堆栈信息,找出死锁或者阻塞的原因;通过JDI,可以动态修改代码并立即生效,进行现场测试。 总...

    深入Java调试体系(JPDA-JDWP)

    JPDA(Java Platform Debugger Architecture)是 Java 平台调试体系结构的缩写,通过 JPDA 提供的 API,开发人员可以方便灵活的搭建 Java 调试应用程序。 JPDA 主要由三个部分组成:Java 虚拟机工具接口(JVMTI),...

    java调试参数

    通过合理设置Java调试参数,开发者可以在开发、测试甚至生产环境中对Java应用程序进行远程调试,这对于定位问题、理解程序运行时的行为至关重要。本文将围绕“Java调试参数”这一主题展开,详细介绍与之相关的各项...

    漫谈调试/调试的基本原理

    在Arm架构中,调试原理类似,但涉及的是TFArm机制,通过改变程序计数器(PC)来实现单步调试。Elastos 2.1平台提供了DebugAPI,包括WriteProcessMemory、ReadProcessMemory等函数,使得一个进程可以操作另一个进程的...

    Java游戏编程原理与实践教程源码

    Java游戏编程原理与实践是计算机科学中的一个重要领域,它结合了Java编程语言的特性与游戏设计的技巧。在这个教程源码包中,包含了多种经典游戏的实现,如推箱子、俄罗斯方块、超级玛丽等,这些都是游戏开发初学者和...

    JAVA智能卡原理与应用开发_11986803_张大...

    Java智能卡原理与应用开发是智能卡技术领域中的一个重要主题,尤其对于Java开发者而言,它涉及到如何使用Java Card技术进行安全、高效的嵌入式系统设计。Java Card是一种在微小的智能卡上运行的Java平台,它使得智能...

    java游戏编程原理与实践教程pdf+源代码

    Java游戏编程原理与实践教程是一本深入探讨如何使用Java语言进行游戏开发的专业书籍,由陈锐、夏敏捷、葛丽萍三位专家共同编著。这本书不仅涵盖了基础的编程概念,还详细介绍了游戏开发中的关键技术和实战技巧。通过...

    Java调度原理及使用

    理解Java调度原理对于优化应用程序性能和确保系统资源的有效利用至关重要。本篇将深入探讨Java中的调度机制,包括线程的创建、优先级、调度策略以及如何在实际开发中合理使用。 一、Java线程的创建 在Java中,可以...

    编译原理课程解释器构造Java源码

    在这个“编译原理课程解释器构造Java源码”中,我们可以推测这是一个基于Java编程语言实现的解释器项目。Java是一种广泛应用的面向对象的编程语言,它的跨平台特性使得它成为构建各种软件工具的理想选择,包括解释器...

    JAVAECLIPSE下配置WINDCHILL远程调试WINDCHILL学习笔记.pdf

    ### JAVAECLIPSE 下配置 WINDCHILL 远程调试详解 #### 一、配置概述 本文档旨在详细介绍如何在 JavaEclipse ...理解 JPDA 的架构和工作原理对于进行高效的远程调试至关重要。希望本文档能对您的开发工作有所帮助。

    Java远程调试

    ### Java远程调试详解 在软件开发领域,尤其是大型分布式系统或...通过本文的详细介绍,相信读者已经掌握了Java远程调试的基本原理、配置步骤及实际操作流程。在实践中,不断积累经验,将使这一技能发挥更大的作用。

    Eclipse远程调试Java代码

    首先,我们需要理解远程调试的基本原理。远程调试允许开发者在本地IDE上对运行在另一台机器上的应用程序进行调试。这通常通过JVM的远程调试接口实现,即使用标准的Java Debug Wire Protocol (JDWP)。JDWP允许IDE与...

    SLR编译原理java代码

    在本资源中,提供的是用Java语言实现SLR编译原理的代码,这对于学习编译器设计和理解SLR解析技术具有极大的帮助。 SLR解析器的工作原理基于一套称为SLR分析表的表格,这个表包含了词法规则、状态以及动作。当解析器...

    JAVA高端进阶开发课程 JAVA应用程序调试技术 从实战角度出发学习JAVA应用程序调试.rar

    在Java编程领域,调试是开发过程中至...无论你是经验丰富的开发者还是初学者,都能从中受益匪浅,提升自己的Java调试能力。通过实践这些技术,你将能够更加高效地调试和优化你的Java应用程序,实现更高质量的软件开发。

    java现代编译原理.rar_java 编译_现代编译原理_编译_编译原理_编译原理 java

    Java现代编译原理是计算机科学中的一个重要领域,它涉及到如何将高级编程语言,如Java,转换为机器可执行的指令。这个主题对于深入理解Java程序的生命周期和性能优化至关重要。以下是对这一领域的详细阐述: 首先,...

    编译原理,词法分析,java

    在编程领域,编译原理是理解计算机语言处理过程的关键部分,它涉及...通过实际操作,你可以深入理解词法分析器的工作原理,以及如何用Java实现这一过程。这不仅可以增强编程技能,还能提升对编程语言底层机制的理解。

Global site tag (gtag.js) - Google Analytics