动态切片工具 javaslicer【2】

前文 简单介绍了项目,根据熊英飞的这篇 An Empirical Study of Fault Localization Families and Their Combinations 开展实验。

Our experiments use the JavaSlicer dynamic slicing tool. JavaSlicer is based on the dynamic slicing algorithm of Wang and Roychoudhury, with extensions for object-oriented programs. The JavaSlicer implementation attaches to the program as a Java agent and re-writes classes as they are loaded into the Java VM.

A test fails by throwing an exception, either because of a violated assertion or a runtime crash. If there is only a single failed test, we use the execution of the statement that throws the exception as the slicing criterion. The slice then contains all statements that may have affected the statement that throws the exception.

If there are multiple failed tests, our experiments apply three strategies from a previous study to utilize multiple slices: union, intersection, and frequency . The first two strategies calculate the union or the intersection of the slices and report a set of statements as results. The frequency strategy calculates the inclusion frequency for each statement and reports a ranked list of statements based on the frequency. The more frequently a statement is included in the slice of a failed test, the more suspicious the statement is.

简单来说:单个失败测试,使用抛出异常的语句的执行作为切片准则。多个失败测试,采用并集、交集和频率的策略。

1.实验环境搭建

使用 b046ed3 的 Master 分支,运行环境与说明一致:

> ubuntu@VM-0-8-ubuntu:~$ javac -version
javac 1.6.0_20
> ubuntu@VM-0-8-ubuntu:~$ mvn -version
Apache Maven 2.2.0 (r788681; 2009-06-26 21:04:01+0800)

执行 assemble.sh,报错 Plugin requires Maven version 2.2.1

配置换成 javac 1.8.0_281 / Apache Maven 3.3.9 则可以正常使用。

搭建 Defect4J 环境的相关内容不再赘述。

2.项目准备工作

以 Lang-61 为例,首先执行 Checkout:

defects4j checkout -p Lang -v 61b -w /home/ubuntu/lang_61_buggy

然后编译,可以借助 test 命令:

defects4j test

# 结果
Running ant (compile.tests)................................................ OK
Running ant (run.dev.tests)................................................ OK
Failing tests: 2
  - org.apache.commons.lang.text.StrBuilderTest::testIndexOfLang294
  - org.apache.commons.lang.text.StrBuilderTest::testLang294

同时获得了错误测试名称。然后执行单元测试,获得 Exception 信息:

java 
	-cp <classpath> 
	org.junit.runner.JUnitCore 
	<test class name> 
# 示例
java 
	-cp /home/ubuntu/lib/junit-4.12.jar: 			# Junit    jar包
		/home/ubuntu/lib/hamcrest-core-1.3.jar: 	# hamcrest jar包
		/home/ubuntu/lang_61_buggy/target/classes:  # defects4j export -p dir.bin.classes 获得
		/home/ubuntu/lang_61_buggy/target/tests 	# defects4j export -p dir.bin.tests   获得
	org.junit.runner.JUnitCore
	org.apache.commons.lang.text.StrBuilderTest		# 删去失败测试::号后面具体方法

# 结果
JUnit version 4.12
......E........
Time: 0.061
There were 2 failures:
1) testIndexOfLang294(org.apache.commons.lang.text.StrBuilderTest)
junit.framework.AssertionFailedError: expected:<-1> but was:<6>
	at junit.framework.Assert.fail(Assert.java:57)	#  -> junit.framework.Assert.fail:57
	at junit.framework.Assert.failNotEquals(Assert.java:329)
	..
2) testLang294(org.apache.commons.lang.text.StrBuilderTest)
java.lang.ArrayIndexOutOfBoundsException
	at java.lang.System.arraycopy(Native Method)	# 本地方法,跳过
	at org.apache.commons.lang.text.StrBuilder.deleteImpl(StrBuilder.java:1114)	#  -> org.apache.commons.lang.text.StrBuilder.deleteImpl:1114
	at org.apache.commons.lang.text.StrBuilder.deleteAll(StrBuilder.java:1188)
	..

FAILURES!!!
Tests run: 73,  Failures: 2

这部分信息,通过 test 自动生成的 failing_tests 文件也可以获得,或者直接从 D4J 项目中 framework/projects/Lang/trigger_tests 中获取。

3.生成跟踪文件

依据以下说明,生成 trace 文件。

You can also trace JUnit tests
java -javaagent:... org.junit.runner.JUnitCore <test class name>

java 
	-javaagent:<tracer.jar>=tracefile:<trace file> 
	-cp <classpath>
	org.junit.runner.JUnitCore 
	<test class name>
# 示例
java  
	-javaagent:/home/ubuntu/javaslicer/assembly/tracer.jar=tracefile:/home/ubuntu/trace/lang_61_1.trace
	-cp /home/ubuntu/lib/junit-4.12.jar:
		/home/ubuntu/lib/hamcrest-core-1.3.jar:
		/home/ubuntu/lang_61_buggy/target/classes:
		/home/ubuntu/lang_61_buggy/target/tests
	org.junit.runner.JUnitCore
	org.apache.commons.lang.text.StrBuilderTest

4.执行动态切片

对跟踪文件执行动态切片:

java 
	-Xmx <memory>
	-jar <slicer.jar>
	-p <trace file> <criterion/local>
	>> <result file>
# 示例 
java 
	-Xmx2g 
	-jar /home/ubuntu/javaslicer/assembly/slicer.jar 
	-p /home/ubuntu/trace/lang_61_1.trace 
	junit.framework.Assert.fail:57
	>> /home/ubuntu/sliceRes/lang_61_1

输出结果:

0.0% done, time left: unknown
..
100.0% done, time left:   0:00:00
finished
The dynamic slice for criterion [junit.framework.Assert.fail:57]:
# 想要的结果
com.sun.proxy.$Proxy0.<init>:-1 ALOAD 0
com.sun.proxy.$Proxy0.<init>:-1 ALOAD 1
..
# 错误行
org.apache.commons.lang.text.StrBuilder.indexOf:1776 ALOAD 4
org.apache.commons.lang.text.StrBuilder.indexOf:1776 ARRAYLENGTH
org.apache.commons.lang.text.StrBuilder.indexOf:1776 ILOAD 3
org.apache.commons.lang.text.StrBuilder.indexOf:1776 ISUB
org.apache.commons.lang.text.StrBuilder.indexOf:1776 ISTORE 5
..
sun.reflect.generics.visitor.Reifier.visitClassTypeSignature:130 ALOAD 0
sun.reflect.generics.visitor.Reifier.visitClassTypeSignature:130 ALOAD 7
sun.reflect.generics.visitor.Reifier.visitClassTypeSignature:130 PUTFIELD sun/reflect/generics/visitor/Reifier.resultType Ljava/lang/reflect/Type;

Slice consists of 6178 bytecode instructions.
Computation took 15.12 seconds.

5.最终数据处理

只保留 org.apache.commons.lang 开头的项目行:

  • 错误测试用例1:剩 132 行,错误行分布在 79 - 83
  • 错误测试用例2:剩 416 行,错误行分布在 248 - 252

而使用 GZoltar 工具统计的 Spectra 有 973 行,切片可以显著缩减可疑语句数量。

附录:Shell脚本

# 写好了发我,谢谢~
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值