This document describes the usage of Pachika. More information on what PACHIKA does and how it works can be found here .
The following steps have been tested under Gentoo, Debian and MacOS 10.5. In theory, the tool should also work under Windows, however, we never tested if it actually does.
Suppose there is a program P . Usually, P behaves correctly so we have a number of passing runs where P behaves as expected. For one run (the failing run f ) however, P crashes. Applying Pachika to this failure involves the following steps:
PACHIKA currently consists of several command line tools, which roughly map to the steps described above. The following sections provide details on how to invoke PACHIKA.
Throughout this document, we will illustrate each step using a real-life example taken from the bug database of AspectJ . Bug 173602 crashes the ASPECTJ compiler. More information on the bug is available here . For each required step, we will first explain the step and then show how this step applies on our example.
To get started, you first have to install PACHIKA:
For the remainder of this file, we assume that PACHIKA is installed in folder $PACHIKA_INSTALL.
To trace a program run, you can use the tracerun.sh script of the tracer. Make sure that you changed the installation directory. The tracer is implemented as a Java bytecode agent . The tracerun.sh script basically builds a command line that invokes Java with some special parameters that activate the tracer. For example, if you normally invoke your program like this:
java -cp lib/myjar.jar mypackage.MyClass foo bar
you can use the tracerun.sh script to trace this execution by calling
$PACHIKA_INSTALL/bin/tracerun.sh -cp lib/myjar.jar mypackage.MyClass foo bar
By default, PACHIKA stores the trace in a file name trace.ser in the working directory. To change that, you can pass a parameter -Dadabu2.resultFilename . For example, to store the trace in file /tmp/trace.ser , you can use the following call:
$PACHIKA_INSTALL/bin/tracerun.sh -Dadabu2.resultfilename=/tmp/trace.ser -cp lib/myjar.jar mypackage.MyClass foo bar
The failing and passing runs for bug 173602 are available in the iBUGS repository. If you want to trace the runs yourself, you need to download the ASPECTJ subject, checkout and build the version for bug 173602 and run the tests. Information on how this is done is available here . The failing run is the one that is provided in the repository. The regression test suite contains several suitable passing runs. In our experiments, we use the valid double binding test in file org.aspectj/modules/tests/ajcHarnessTests.xml .
If you don't want to trace the runs yourself, you can download the failing and passing trace files (approx. 80 MB each). The output of the failing run contains the following stack trace:
[java] java.lang.NullPointerException [java] at org.aspectj.ajdt.internal.compiler.ast.InterTypeMethodDeclaration.resolve(InterTypeMethodDeclaration.java:92) [java] at org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1109) [java] at org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration.resolve(AspectDeclaration.java:114) [java] at org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1188) [java] at org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.resolve(CompilationUnitDeclaration.java:366) [java] at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.process(Compiler.java:625) [java] at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:392) [java] at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performCompilation(AjBuildManager.java:988) [java] at org.aspectj.ajdt.internal.core.builder.AjBuildManager.doBuild(AjBuildManager.java:264) [java] at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:180) [java] at org.aspectj.ajdt.ajc.AjdtCommand.doCommand(AjdtCommand.java:112) [java] at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:60) [java] (... 17 lines...) [java] [ 0] [abort 0]: abort ABORT -- (NullPointerException) null [java] null [java] java.lang.NullPointerException [java] at org.aspectj.ajdt.internal.compiler.ast.InterTypeMethodDeclaration.resolve(InterTypeMethodDeclaration.java:92) [java] at org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1109) [java] at org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration.resolve(AspectDeclaration.java:114) [java] at org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1188) [java] at org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.resolve(CompilationUnitDeclaration.java:366) [java] at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.process(Compiler.java:625) [java] at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:392) [java] at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performCompilation(AjBuildManager.java:988) [java] at org.aspectj.ajdt.internal.core.builder.AjBuildManager.doBuild(AjBuildManager.java:264) [java] at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:180) [java] at org.aspectj.ajdt.ajc.AjdtCommand.doCommand(AjdtCommand.java:112) [java] at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:60) [java] (... 17 lines...) [java] [java] F
The distribution contains a script minemodels.sh that assembles the command line needed for extracting the set of visible objects. The synopsis of the script is as follows:
usage: SimpleUsedObjectSetMiner -heapPathLength <int> The maximum number of steps on the heap the miner follows (aka. depth) -includeAStores Include objects stored in local variables. -methodPattern <pattern> Regular expression for accepted methods (see documentation for java.util.regex) -outputFile <file> File were serialized information about visible objects is stored into. -traceFile <file> File that contains the program trace (e.g. trace.ser) -verbose Output visible objects to System.out at the end of the trace.
This script reads the trace and determines the set of reachable objects when a given method starts. The method name is passed as a regular expression with parameter methodPattern (see this link for regular expression syntax).
For the sake of simplicity, we will only mine relevant objects for the top-most method, which is resolve . To mine the set of relevant objects for the failing run, we invoke the miner as follows:
$PACHIKA_INSTALL/bin/minevisibleobjects.sh -heapPathLength 1 -methodPattern \ "org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.resolve\([^)]*\)" \ -outputFile visibleobjects_failing.ser -traceFile failing_173602.ser
The method name pattern is extracted from the output of the failing run (see above). For technical reasons, the syntax name for the method name follows the virtual machine specification . A method identifier consists of the fully qualified class name with slashes instead of dots, and the method name followed by the signature. To keep things simple, we use a simplified regular expression in our example.
To mine models for the passing run, we use a slightly modified command line:
$PACHIKA_INSTALL/bin/minevisibleobjects.sh -heapPathLength 1 -methodPattern \ "org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.resolve\([^)]*\)" \ -outputFile visibleobjects_passing.ser -traceFile passing_173602.ser
The model miner takes as input the trace file and the set of relevant objects. It mines an object behavior model for each relevant object and stores all models in a file. For convenience, we provide a script named minemodels.sh that builds the command line for the model miner. The script can be found in file bin/minemodels.sh . The synopsis of this script is as follows:
-heapPathLength <int> The maximum number of steps on the heap the miner follows (aka. depth) -outputFile <file> File model data is written to. -traceFile <file> File that contains the program trace (e.g. trace.ser) -verbose Output models to System.out -voFile <file> File with serialized data about relevant objects.
To mine models from the failing run, we invoke the script as follows:
$PACHIKA_INSTALL/bin/minemodels.sh -heapPathLength 1 -voFile visibleobjects_failing.ser -traceFile failing_173602.ser -verbose -outputFile models_failing.ser
$PACHIKA_INSTALL/bin/minemodels.sh -heapPathLength 1 -voFile visibleobjects_passing.ser -traceFile passing_173602.ser -verbose -outputFile models_passing.ser
The final step is to run PACHIKA with the results of the previous steps. For convenience, we again provide a script (named runpachika.sh ) that facilitates the call. The script takes the following parameters:
-appClassPath <cp> Class path of the application that is to be executed. -compileClassPath <cp> Class path for compiling fixes. -failingRunModels <file> File with models from failing run. -passingRunModels <file> File with models from passing run. -tempDirectory <dir> Temporary directory where fixes are compiled in. -testCommand <file> Command that executes the failing test. -workingDirectory <dir> Working directory for executed processes.
Parameter appClassPath contains the class path that is used to execute the program. This is necessary for PACHIKA to be able to analyze the program classes for suitable fix locations. The testCommand parameter contains a command that executes the failing run. Pachika classifies an execution as passing if the process return value is 0, and failing otherwise. Fixes are generated according to the differences in passing and failing models. The tempDirectory is used to compile candidate fixes. If a candidate fix makes the failing run pass, it is output to System.out .
Before we can run PACHIKA, we first have to create a small wrapper script wrapper.sh that executes the failing run. For more information on how specific runs are executed, please refer to the iBUGS documentation . The application class path for ASPECTJ contains the test drivers and resources built by ASPECTJ. You can either use the files from your iBUGS installation or download the test driver jar file here . The call below assumes that the jar file is located in folder $IBUGS_INSTALL. To run PACHIKA, we execute the script with the following parameters:
$PACHIKA_INSTALL/bin/runpachika.sh -failingRunModels models_failing.ser \ -passingRunModels models_passing.ser -tempDirectory /tmp -testCommand wrapper.sh \ -workingDirectory /tmp/working \ -compileClassPath "$PACHIKA_INSTALL/lib/asm-util-3.1.jar:$PACHIKA_INSTALL/lib/asm-tree-3.1.jar:$PACHIKA_INSTALL/lib/util-0.3.jar:$PACHIKA_INSTALL/lib/adabu2-pachika-0.4.jar:$PACHIKA_INSTALL/lib/asm-3.1.jar" \ -appClassPath "$IBUGS_INSTALL/ibugs_173602.jar"
From the output we can see that PACHIKA generates 2 fixes that correct the failure. However, verification against the test suite shows that only one of them doesn't break the test suite.
If you have comments or run into problems with PACHIKA, please don't hesitate to send an email to dallmeier@cs.uni-saarland.de .