Jex
A Tool for Analyzing Exception Flow in Java Programs

Updates

22 June 2007Version 1.2.1This page has moved URL and the links have been updated. The Jex tool is a legacy project that is no longer maintained.
8 March 2002Version 1.2.1A few bug fixes and support for performing a single pass through the code.

Overview

Jex is a static analysis tool that provides information about the exceptions that can be raised in a Java program. For each method of each class, Jex outputs a description of all exceptions that can be raised in the method. The description shows the origin of each exception.

Here is an example describing the flow of exceptions for an hypothetical constructor, in the Jex format.


<init>(java.lang.String,boolean) throws IOException
{
   java.lang.SecurityException:SecurityManager.checkWrite(java.lang.String);
   try
   {
      java.io.IOException:java.io.FileOutputStream.openAppend(java.lang.String);
      java.io.IOException:java.io.FileOutputStream.open(java.lang.String);
      java.lang.NullPointerException:*environment*;
   }
   catch( java.lang.IOException )
   {
      throws java.io.FileNotFoundException;
   }
}

In this example, we see that an SecurityException can be raised as a result of the call to method checkWrite of class SecurityManager. Furthermore, in the try block, IOExceptions can result from the calls to methods openAppend and open of class FileOutputStream, and a NullPointerException can be raised by the run-time environment. The catch clause declares to catch IOException and in the corresponding block, a FileNotFoundException is explicitly raised using the keyword throw. General information about the information contained in Jex files can be found below. The view of exception flow produced by Jex is more precise and more complete than the information available through exception interfaces (i.e, the "throws" list in method declarations).

Precise information

Jex includes more precise information because it includes the types of the exceptions raised by subsumption and by polymorphic calls. For example, if a method declares to raise IOExceptions, but in reality raises both IOExceptions and FileNotFoundExceptions (a subtype of IOException), the exception interface must only declare the supertype (IOException). Jex will report the different subtypes of IOExceptions that can be raised.

Jex also reports the origin of exceptions stemming from polymorphic calls by using a conservative class hierarchy analysis algorithm.

Complete information

The information reported by Jex is also more complete because it includes information about the types of unchecked exceptions that can be raised.

General information on Jex

Jex was developed in 1998 in the Department of Computer Science at the University of British Columbia by Martin Robillard with contributions from Gail Murphy. It was introduced in this ESEC/FSE'99 paper. This TOSEM paper has the most complete description of Jex.


Download and Installation

This version of Jex was developed as an extension to KJC, an open source Java compiler. It also uses the gnu.getopt package and antlr.

Jex is freely available under the terms of the GNU Public License.

Jex and its dependencies are written in Java. To install:

  1. Download Jex and unzip it.
  2. Add dist\Jex-1.2.jar to your CLASSPATH.
  3. Add lib\antlr.jar to your CLASSPATH.
  4. Add lib\getopt.jar to your CLASSPATH.
  5. Add the Java libraries (typically, jdk1.3/jre/lib/rt.jar) to your CLASSPATH
  6. Download this file (genstubs1.3.txt) if you are using JDK1.3, or this one (genstubs1.2.txt) if you are using JDK1.2.
See below for instructions on how to perform analyses using Jex. Here is a quickstart example (you must at least generate the stubs before you try the example).


User Guide

The basic unit of information needed by the Jex tool is a Jex file: a text file containing exception flow information. In order to produce a Jex file for a target class, the Jex files for all the classes used by this target class must exist. The approach Jex uses to deal with bootstrapping, cyclic dependencies, and classes with unavailable source code, is to generate a bunch of stubs (minimal jex files) for all classes considered for the analysis and iterate until fix points are reached. The analysis always converges. To manage all the jex files, Jex uses a "Jex Path", a root directory where jex files are stored in a hierarchical directory structure similar to the one of the CLASSPATH.

Setting up the Jex Path and generating the stubs

The first thing to do is to generate the stubs for all (or part of) the java class libraries. These stubs are Jex files that typically won't be augmented by more analysis, and thus can be generated once and left alone. It is NOT necessary to have the source code for generating stubs for a class.

To generate stubs for the java libraries:

  1. Put the genstubs1.3.txt (or genstubs1.2.txt) file in a directory somewhere.
  2. Open it. The first line is <jexpath> c:\jexfiles. Change c:\jexfiles for the directory you select as the root for all the jex file hierarchy.
  3. The following lines correspond to all the java* libraries. Remove any you do not want to generate (it's always possible to generate them later).
  4. Add genstubs lines for any packages you use and do not have the source code or do not wish to analyze.
  5. In the directory where you put the genstubs.txt file, enter: java ca.ubc.cs.jex.Jex -g genstubs.txt
This will create Jex files for all the classes of all the packages specified in genstubs.txt. The stubs provide minimal information about the exceptions raised by each methods (i.e., the exceptions it declares). For classes for which the source code is not available, this is all that can be achieved. For classes for which the source code is available, further analysis is possible.

You can now try the quickstart example, or read on for general information.

Setting up an analysis

To analyze source code with Jex, it is necessary to write a Jex configuration file. Here's a template. The file must follow the following rules:

<token>value \n

Where <token> is either: <jexpath>, <package>, <file>, or <dir>

The <jexpath> value should be the root directory for jex files. It is only possible to specify one Jex path. If many <jexpath> tokens are found in the Jex config file, the value of the last one will be used.

The <package> value should be a valid, fully-qualified package name (e.g., java.lang), to include for class-hierarchy analysis. Class hierarchy analysis is used to conservatively determine what method bodies can be executed for each method call. As many package descriptors as desired can be used. For instance, if java.lang and java.io are specified, calls to Object.toString() will be considered to raise all the exceptions raised by the calls to toString() of all the classes in java.io and java.lang. If a method call is detected in the source code for a class that is not part of the classes included with the packages descriptors, a warning will be issued.

The <genstub> value should be a valid, fully-qualified package name (e.g., com.mypackage), to generate stubs for at the beginning of an analysis. Stubs for library code that is not analyzed should be only generated once and left alone. A genstub command for them is not necessary. However, the <genstub> can be added to a config file when it is desired to re-generate jex files from scratch. This is necessary when source code is modified and jex files become out of sync. A command-line option gives the user the possibility of regenerating the jex files or not, so adding <genstub> is not a strong commitment.

the <dir> value should be a valid directory where Java source files can be found.  The <dir> value indicates to jex to analyze all the java source files in the specified directory.

The <file> value should be a valid java source file.  The <file> value indicates to jex to analyze the single source file.

Any combinations of <file> and <dir> tokens can be used.

When writing a jexconfig file, it is important to keep in mind that Jex processes all the source files specified until a fix point is reached. This can be slow. To speed up the analysis of a entire application, it is faster to analyze separate, self-contained groups of source files separately. For instance, if I have packages A (50 files), B (100 files), and C (200 files), I could include these 3 packages using the dir command and launch an analysis. This would result in analyzing 350 files until a fix point is reached. If package C is known not to depend on neither A nor B, it will be faster to analyze C in isolation, and then analyze A and B together.

Running an analysis

Jex makes heavy use of introspection. To successfully run an analysis, the Java code to be analyzed must be compiled and the corresponding class files must be properly installed and visible through the CLASSPATH. The java class libraries (typically, rt.jar) must also be explicitly in the classpath.

To run an analysis, write a jexconfig file describing the desired analysis, and enter:

java ca.ubc.cs.jex.Jex jexconfig.txt

Available command-line options are:
-g generate stubs for all packages specified with <genstub> in the config file
-h shows a help message
-v shows the version
-1 (one, not lowercase "L") performs a single pass through the file and dumps a checksum indicating how much exception information was calculated. Useful for large analyzes that can run out of memory.

Interpreting the results

Once the analysis is complete, Jex will generate a file jex-report.txt in the directory from which the application was launched. This report contains the following information:

  1. The date and time at which the report was generated
  2. The Jex path used
  3. The packages used for class hierarchy analysis
  4. The Java files analyzed
  5. The times for each segment of the analysis
  6. Missing Jex files. These are more serious errors. They indicate that the information produced for the java files analyzed is incomplete because some jex files were missing. Stubs or complete jex files should be provided for these.
  7. Other errors. These correspond to bugs in Jex. Hopefully there should be none.
  8. Warnings. Warnings consists in all the methods that were not found in the method database used for class hierarchy analysis. This is not necessarily a problem if those methods are known to not be overridden, or if the information is deemed irrelevant or too conservative.
The actual results of the analysis are found in the actual Jex files generated. A Jex file contains, for each method in a class, a description of the exception flow. The description consists in exception descriptors, representing exceptions that can potentially be raised in a program. These exception descriptors are presented in the try/catch/finally context in which they appear in the program. Exception descriptors can be: <exception type>:*environment*, e.g., java.lang.NullPointerException:*environment*

This is an exception that can be raised by some operations of the JVM. These correspond to section 15.6 of the Java language specification.

<exception type> <class><method signature>, e.g., java.io.IOException:java.lang.io.File.getCanonicalPath()

This is an exception that can be raised by a method call.

throws <exception type>, e.g., throws IOException

This is an exception that can be raised explicitly using the throws keyword.


Example

You can make sure your installation works using the following example, taken from the Java Tutorial. This example assumes that you have successfully generated the stubs for the Java libraries.
  1. Download this file, and extract it using a zip utility and then extract it using jar xvf so that the directory structure is visible.
  2. Add the directory where you extracted the file (i.e., the parent directory of jexex) to your CLASSPATH
  3. If you have not already done do, add the java run-time (typically, jdk1.3/jre/lib/rt.jar) to your CLASSPATH
  4. Open the file jexex/jexconfig.txt
  5. Change the first line to reflect where you want your jex files to reside. Make sure this directory is writable.
  6. In the last 3 lines, replace "c:\javacode" by the full path of the directory where you extracted the jexex directory.
  7. In the jexex directory, enter java ca.ubc.cs.jex.Jex -g jexconfig.txt
  8. The jex report generated should look like this.


Contact

Jex is an unsupported legacy project. For general questions, please contact Martin Robillard.


Last updated 22 June 2007