Introduction

This document describes the usage of Pachika. More information on what PACHIKA does and how it works can be found here .

Requirements

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.

Overview

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:

  1. First, the execution of of passing and failing runs is traced. Each run produces a trace file, which is needed for the next steps.
  2. In the next step, we manually extract the failure stack trace from the output of the failing trace.
  3. In the third step, the trace of the failing run is examined to identify the set of relevant objects. Currently, all objects relevant that are reachable by methods on the stack when the failing run is executed are considered to be relevant.
  4. The next step is to mine object behavior models for all relevant objects.
  5. The next step is to repeat the last two steps for all passing runs.
  6. The final step is to invoke PACHIKA with passing and failing models.

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.

An illustrating example

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.

Getting Started

To get started, you first have to install PACHIKA:

  1. Make sure that you have Java 1.6 installed and ready to run.
  2. Go to the Downloads page and download the most recent version of the tracing component and PACHIKA itself.
  3. Both the tracer and PACHIKA come with ready-to-use bash scripts located in folder bin . To use those scripts, you have to edit them and configure the installation directory manually. The corresponding variable can be found in the second line in all scripts. Please make sure that you do this for all scripts (currently 4).

For the remainder of this file, we assume that PACHIKA is installed in folder $PACHIKA_INSTALL.

Tracing a Run

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

Bug 173602

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

Mining Relevant Objects

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).

Bug 173602

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

Mining models

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.

Bug 173602

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

Running Pachika

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 .

Bug 173602

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.

Questions

If you have comments or run into problems with PACHIKA, please don't hesitate to send an email to dallmeier@cs.uni-saarland.de .