http://www.ibm.com/developerworks/cn/java/j-ibmjava5/index.html
激活和控制跟踪
可以通过多种机制激活和控制跟踪引擎:
通过命令行选项-Xtrace
使用跟踪属性文件 通过
com.ibm.jvm.Trace
API,使用 Java 代码进行动态控制 使用跟踪触发器事件 从外部代理使用基于 C 的 JVM RAS Interface(JVMRI)
控制跟踪的主要方法是使用命令行选项 -Xtrace
,或者在选项集比较长或复杂的情况下,使用可选的跟踪属性文件。
-Xtrace
选项由一系列标志或标志-值对组成,这些设置用来决定跟踪应该写到 stderr
、内部缓冲区还是二进制文件;是启用方法跟踪、JVM 跟踪,还是两者都启用;应该跟踪哪些跟踪点;是跟踪对跟踪点的任何修改,还是在发生事件时触发转储。
激活跟踪的基本知识
在使用 IBM 的跟踪设施时,需要决定的第一件事是应该将跟踪输出定向到哪个目的地。表 1 简要描述这些目的地以及将多少跟踪点数据发送给它。例如,print
将所有跟踪数据定向到 stderr
,minimal
将每个跟踪点的数据子集定向到内存缓冲区,然后又可以使用 output
选项将这些缓冲区中的数据捕捉到文件中。
表 1. 跟踪目的地
关键字 | 功能 |
---|---|
minimal |
将选择的跟踪点(只有标识符和时间戳)定向到核心缓冲区。不记录相关联的跟踪数据。 |
maximal |
将选择的跟踪点(标识符和时间戳以及相关联的数据)定向到核心缓冲区。 |
count |
统计在 JVM 的生命期内调用选择的跟踪点的次数。 |
print |
将选择的跟踪点定向到 stderr ,不进行缩进。 |
iprint |
将选择的跟踪点定向到 stderr ,进行缩进。 |
external |
将选择的跟踪点定向到 JVMRI 监听器。 |
exception |
将选择的跟踪点定向到为异常保留的核心缓冲区。 |
应该将每个关键字的值设置为所需的跟踪点。例如:
-Xtrace:maximal=all
将来自所有 JVM 跟踪点的所有信息记录到内部回绕缓冲区中。-Xtrace:iprint=awt
将所有 JVM 内部 AWT 跟踪点记录到 stderr
,在进入和退出时进行缩进。-Xtrace:iprint=mt
激活方法跟踪并将输出发送到 stderr
,进行缩进。 仅仅使用表 1 中的选项并不会生成任何输出;必须单独提供要跟踪的方法名。注意,IBM Diagnostics Guide 的第 32 章 “Tracing Java applications and the JVM” 详细讨论了所有跟踪选项(见 参考资料)。
将跟踪数据放进内部缓冲区中
使用存储内缓冲区进行跟踪是非常高效的,因为在探测到问题或者使用 API 将缓冲区写入文件之前,不执行显式的 I/O。缓冲区被分配给每个线程,这防止线程之间发生冲突并防止各个线程的跟踪数据相互干扰。例如,如果某个线程没有被调度,当转储缓冲区时它的跟踪信息仍然是可用的。
要查看跟踪数据,必须转储缓冲区并进行格式化。当发生以下情况时,自动进行缓冲区的转储:
com.ibm.jvm.Trace.snap()
Java API TraceSnap
函数 将跟踪数据放进文件中
可以连续地将跟踪数据写到文件中,作为存储内跟踪的扩展;但是在这种情况下不是为每个线程分配一个缓冲区,而是至少分配两个。当一个跟踪缓冲区满了时,将它写到文件系统中,这使线程能够连续运行。根据跟踪量、缓冲区大小和输出设备的带宽,可以将多个缓冲区分配给给定的线程,从而与生成跟踪数据的速度相匹配。
要将 minimal
或 maximal
跟踪选项的输出写到文件中,应该使用 output
关键字,对于 exception 选项使用 exception.output
关键字:
-Xtrace:maximal=all,output=trace.out
将跟踪数据写到文件 trace.out 中。 -Xtrace:maximal=all,output={trace.out,5m}
将跟踪数据写到文件 trace.out 中,当文件达到 5MB 时进行回绕。 -Xtrace:maximal=all,output={trace#.out,5m,5}
将跟踪数据依次写到 5 个文件中,每个文件 5MB,#
用文件的序号代替。在这个示例中,创建文件 trace0.out 到 trace4.out,每个文件包含最近的 5MB 跟踪数据。当 5 个文件都填满时,JVM 依次覆盖 trace0.out 到 trace4.out。这个选项可以创建的最大文件数是 36 个,#
字符被替换为 0 到 9,然后是 A 到 Z。 还可以在文件名中进行以下替换:
%p
:Java 进程的 ID。 %d
:yyyymmdd 格式的当前日期。 %t
:hhmmss 格式的当前时间。 对跟踪文件进行格式化
跟踪格式化器(trace formatter) 是一个可以在任何平台上运行的 Java 程序,可以对来自任何平台的跟踪文件进行格式化。IBM SDK 在 core.jar 中提供了这个格式化器,它还需要一个称为 TraceFormat.dat 的文件,其中包含格式化模板。这个文件在 jre/lib 中。可以用以下命令行启动跟踪格式化器:
java com.ibm.jvm.format.TraceFormat input_file [output_file]
|
在这里,com.ibm.jvm.format.TraceFormat
是跟踪格式化器类,input_file
是要进行格式化的二进制跟踪文件的名称,output_file
是可选的输出文件名。如果没有指定输出文件,那么默认的输出文件名是输入文件名加上 .fmt。
动态记录器
IBM VM 跟踪设施包含一个动态记录器(flight recorder),它连续地将来自关键跟踪点子集的数据捕捉到内存缓冲区中。当出现运行时问题时捕捉这些缓冲区,可以用来诊断问题并分析 VM 的历史。VM 初始化过程用一小组跟踪点启动跟踪,这些跟踪点被捕捉到回绕式存储内缓冲区中。可以使用这些信息初步诊断 Java 运行时中的任何问题,并确保 -verbose:gc
选项提供的数据子集总是可用的。垃圾收集数据也出现在 Java 转储文件中。
内部的动态记录器使用一个命令行选项:
-Xtrace:maximal=all{level1},exception=j9mm{gclogger} |
如果在命令行上指定 -Xtrace
,或者在属性文件中设置它,那么清除激活的跟踪点集。
方法跟踪
可以利用 Java 方法跟踪来跟踪每个线程对方法的调用,包括进入方法和退出方法,这种跟踪针对 Java 运行时的 IBM 实现上运行的任何代码进行。这不需要对 Java 代码进行任何手工处理,可以使用它跟踪 JCL、第三方包或应用程序代码。
方法跟踪功能尤其适合调试发生竞争状态和在方法之间传递了不合适的参数而导致异常的情况。由于跟踪时间戳具有毫秒级的精度,方法跟踪还可以用来调试性能问题。
在命令行上调用方法跟踪的办法是,添加 methods
关键字标志并将 mt
设置给目的地关键字之一(maximal
、minimal
、print
)。methods
关键字允许按照类、方法名或这两者选择要跟踪的方法。可以使用通配符和取反操作符 !
建立复杂的选择条件。例如:
-Xtrace:print=mt,methods={*.*,!java/lang/*.*}
:对于除了 java.lang
包中的方法和类之外的所有方法和类,将方法跟踪写到 stderr
中。-Xtrace:maximal=mt,output=trace.out,methods={tests/mytest/*.*}
:对于 tests.mytest
包中的所有方法,将方法跟踪写到文件中。(注意,这个选项只选择要跟踪的方法。) 在发生跟踪事件时触发
IBM 跟踪引擎最强大的特性之一是它能够在发生跟踪事件时触发,这有助于创建目的明确的跟踪输出并减少产生的跟踪数据量。这会提高被调试的应用程序的性能(由于开销大大降低了)和解释数据的速度(由于多余的数据减少了)。
跟踪引擎能够在任何给定的跟踪点上触发,包括 VM 内部的跟踪点或 Java 方法,而且在发生事件时可以执行许多操作,见表 2:
表 2. 跟踪引擎操作
关键字 | 功能 |
---|---|
suspend |
暂停所有 跟踪(特殊跟踪点除外)。 |
resume |
恢复所有 跟踪(由 resumecount 属性和 Trace.suspendThis() 调用暂停的线程除外)。 |
suspendthis |
增加这个线程的暂停计数。非零的暂停计数会停止这个线程的所有跟踪。 |
resumethis |
减少这个线程的暂停计数(如果这个值大于零的话)。如果暂停计数到达零,那么这个线程的跟踪就会恢复。 |
sysdump |
生成非破坏性的系统转储。 |
javadump |
生成 Java 转储。 |
heapdump |
生成堆转储。 |
snap |
将所有激活的跟踪缓冲区写到当前工作目录中的一个文件中。 |
可以使用 trigger
命令行关键字激活触发跟踪,这个关键字决定在发生事件时执行表 2 中的哪些操作。注意,触发选项控制其他跟踪属性已经选择的跟踪数据是正常生成,还是被阻塞。
使用以下格式指定方法事件上的触发:
-Xtrace:trigger=method{method spec, entry action, exit action, delay count, match count} |
当进入与 method spec 匹配的任何方法时,执行 entry action。当退出方法时,执行 exit action。如果指定了 delay count,那么只有当进入和退出的次数大于 delay count 时才执行 entry action 和 exit action。如果指定了 match count,那么操作的执行次数不超过这个值。请考虑以下示例:
-Xtrace:trigger=method{java/lang/StackOverflowError*, sysdump} |
这在第一次(而且只在第一次)调用 StackOverflowError
方法时(进行调用的是
方法),创建一个非破坏性的系统转储。
可以使用 suspend
和 resume
选项并结合 resumecount
或 suspendcount
关键字来暂停和恢复单独的线程或所有线程:
-Xtrace:resumecount=1 -Xtrace:trigger=method{HelloWorld.main,resume,suspend} |
这些选项在调用 HelloWorld.main()
时开始跟踪所有线程,在 HelloWorld.main()
返回时停止跟踪。这实际上意味着在 Java 运行时启动时不进行跟踪,只在 HelloWorld 应用程序运行期间生成跟踪数据。
用跟踪引擎能够实现什么?
可以使用跟踪引擎为 Java 运行时本身或其中运行的应用程序代码中的任何问题生成数据流或历史数据。这些历史数据加上转储引擎生成的状态数据能够帮助开发人员了解和调试许多问题。