CSDN 中已有两篇文章 参考1、参考2
JavaSlicer 是 Saarland 大学 Clemens Hammacher 开发的开源动态切片工具。官方站、Github
安装
- JDK
- Apache Maven
因为 JDK 1.8 引入了 JavaSlicer 无法处理的新特性,所以目前建议使用1.6和1.7。文档中给出的配置是:
javac 1.6.0_20
Apache Maven 2.2.0 (r788681; 2009-06-26 15:04:01+0200)
> cd javaslicer
> ./assemble.sh
> ls -lh assembly
执行可以看到四个 jar 包
slicer.jar | traceReader.jar | tracer.jar | visualize.jar |
---|
模块/组件
- Tracer:这是生成 Java 程序执行跟踪文件的 JavaAgent。跟踪文件包含所有已加载类的字节码表示形式,以及重构每个线程的执行跟踪的所有信息。
- TraceReader:包含打开与处理跟踪文件所需的类,它为执行跟踪提供前向和后向迭代器。
- Core:切片组件的核心。它使用 TraceReader 组件处理跟踪文件,并计算此运行中的所有动态依赖项。切片器本身就建立在此基础上。它累积动态依赖关系以计算后向切片。
- Common:包含其他几个组件中使用的类。
- Jung:按需创建动态依赖关系的 Jung 图,并可将其可视化。但因其布局算法差,只适用于小图形。
使用
使用包含 java agent 的 tracer.jar 创建 java程序运行的跟踪。为了使所有调试信息(比如变量和名行号),应该使用 javac -g
编译程序。
参数 | 说明 |
---|---|
-g | 生成所有调试信息 |
-g:none | 不生成任何调试信息 |
-g:[keyword list] | 生成指定关键词的调试信息 source、lines、vars |
> java -javaagent:assembly/tracer.jar=help
Use the java agent this way: java -javaagent:tracer.jar=<option[:value]>,<option[:value]>,... -jar program.jar <programoptions>
These are the available agent options:
#用ASM validators检查instrumented的字节码
check (true/false): do check the instrumented bytecode using ASM validators
#选择跟踪文件的压缩算法
compression (none/gzip/sequitur): select the compression algorithm for the trace file
#执行其他检查和详细输出
debug (true/false): do additional checks and verbose output
#帮助
help print this help
#跟踪文件的输出目标
tracefile the output destination for the trace file
ERROR: no logfile specified
#只需要将javaagent附加到Java程序,即可创建跟踪文件。是否执行可运行的JAR并不重要
> java -javaagent:assembly/tracer.jar=tracefile:test.trace -jar evaluation/dacapo-2006-10-MR2.jar -s small pmd
#类路径中的其他类文件
> java -javaagent:... -cp bin/classes:resources my.package.ClassName
#JUnit单元测试
> java -javaagent:... org.junit.runner.JUnitCore <test class name>
控制台查看完整的跟踪:
> java -jar assembly/traceReader.jar test.trace
traceReader 的说明:
> java -jar assembly/traceReader.jar -h
Usage: TraceResult [<options>] <file>
where <file> is the input trace file, and <options> may be one or more of
#过滤掉的指令
-f,--filter <filter> (none/labels/additionals) which instructions to filter out (default: additionals =
labels added during instrumentation)
#帮助
-h,--help print this help and exit
#仅输出跟踪长度
-l,--length do only output the trace length
#计算长度时显示进度
-p,--progress show progress while computing the trace length (only effectfull together with --length)
#选择切片的线程ID(默认主线程)
-t,--threadid <threadid> thread id to select for trace output (default: main thread)
The output of the trace itself will have six fields:
#从0开始递增的计数器
- Nr: just a continuously increasing counter, starting at 0
#实例号,迭代跟踪时始终不变
- intern Nr: this is the instance number, which will always be identical when iterating the trace
#指令的类名、方法名、行号
- Location: Class name, method name and line number of the instruction
#指令的堆栈深度,比如main是堆栈帧最外层1
- Dep: Stack depth of the instruction (1 for outermost stack frames, like main)
#指令出现的次数(被访问频率)
- OccNr: The occurence number of that single instruction (how often was it visited before)
#字节码指令的文本表示形式
- Instruction: Textual representation of the bytecode instruction
trace 是后向输出的,意味着Nr、intern Nr 和 OccNr 从 trace 的末尾开始计数。如果过滤掉了特定的 instructions,intern Nr 可能会有差异。默认情况下,在 instrumentation 过程中插入的标签会被过滤掉。可以在其上运行动态切片,同时应为 JVM 提供更多内存。
> java -Xmx2g -jar assembly/slicer.jar -p test.trace java.util.HashMap.clear:614
slicer 说明:
> java -jar assembly/slicer.jar -h
Usage: Slicer [<options>] <file> <slicing criterion>
where #输入的跟踪文件
<file> is the input trace file
#切片规则
<slicing criterion> has the form <loc>[(<occ>)]:<var>[,<loc>[(<occ>)]:<var>]*
#选项
<options> may be one or more of
#帮助
-h,--help print this help and exit
#多线程(true或1启用)
-m,--multithreaded <value> process the trace in a multithreaded way (pass 'true' or '1' to enable, anything else
to disable). Default is true iff we have more than one processor
#显示动态切片进度
-p,--progress show progress while computing the dynamic slice
#选择切片的线程ID(默认主线程)
-t,--threadid <threadid> thread id to select for slicing (default: main thread)
#对已调用但未跟踪的方法发出警告
-u,--warn-untraced warn once for each method which is called but not traced
切片标准
- 对特定指令的执行进行切片(即从控制依赖开始)
java.util.HashMap.clear:614
切片包含指定行上的所有指令,以及导致这些指令执行的指令。
- 对特定数据进行切片
java.util.HashMap.clear:614:{tab,modCount}
切片包含影响局部变量 tab 和 modCount 值的指令(在614行 java.util.HashMap.clear 方法中)。局部变量不必出现在此行中,甚至可以省略行号,则会对方法中该变量的最后一个值进行切片。在此形式中,指定行上的指令只有在其生成的值被该行上的任何其他指令使用时,才会添加到切片中。
- 对执行和特定行中使用的所有数据进行切片
java.util.HashMap.clear:614:*
切片将是从指定指令开始的控制和数据依赖的传递闭包。通过逗号分隔,可以为一个切片指定多个切片标准 java.util.HashMap.clear:614:*,java.util.HashMap.put:373:{hash}
。但如果跟踪的局部变量是尚未写入方法中的参数,则切片可能为空。在大多情况下,必须使用切片标准。甚至还可以用 Jung 库可视化切片。
> java -Xmx2g -jar assembly/visualize.jar -p test.trace java.util.HashMap.clear:614