TorqueWrench is a tool which does analysis of Java bytecode. TorqueWrench encourages the adoption of good coding practices by automating identification of dubious or non-standards compliant code. Using TorqueWrench is simple. It is added somewhere in your build process after Java code is compiled and generates a report of problems that it found.
TorqueWrench is implemented entirely in Java. TorqueWrench will work on any platform that has an implementation of Java 1.5 or higher. Supported platforms include Linux, Mac OS X, Solaris, and Windows. TorqueWrench supports analysis of Java bytecode generated by any version of any Java compiler up to the 1.5 JVM specification.
TorqueWrench uses a simple license management system that is designed to be as non-intrusive as possible. Embedded in the JAR file is a license file describing the allowable uses. If licensed for use only on a single node, TorqueWrench will exit if it detects more than one instance running with the same license key on the local network.
TorqueWrench also downloads a version file from the StackFrame web site to determine if a newer version is available for use with your license key.
TorqueWrench is delivered on both CD and over the Internet as both a gzipped TAR file and as a ZIP file. The TAR and ZIP files have the exact same contents and are shipped in both formats in order to be convenient for both Windows and Unix users. Unpack one of the files into any directory that is accessible to the code to be tested (e.g. /usr/local). A directory called TorqueWrench will be created which will contain the program, a wrapper script to aid in command line invocation, and this document. For future reference, the installation directory will be referred to as TW_HOME and the expansion of it as $TW_HOME. For example, if the file is expanded at /usr/local, TW_HOME will be /usr/local/TorqueWrench; if it is expanded at D:\devel, TW_HOME will be D:\devel\TorqueWrench.
TorqueWrench can be invoked either from the command line or from Ant.
TorqueWrench can be invoked from the command line in two ways. Either way, the options supplied are the same. TorqueWrench simply takes a list of JAR, WAR, EAR, RAR, and .class files to process. If an argument is a directory, it is recursively scanned for JAR, WAR, EAR, RAR, and .class files to process. In the following examples, assume that TorqueWrench will be run over three files - an application in application.jar, a library in library.jar, and a test class in test.class.
$JAVA_HOME, if that environment variable is set. If $TW_HOME is added to the PATH, simply execute 'torquewrench application.jar library.jar test.class'.Options can be specified on the command line before the list of JAR, WAR, EAR, RAR, .class files, and directories.
Generates an HTML file in the report for each class that is analyzed. This can be useful for determining things like what methods invoke a given method. This is disabled by default as it can potentially generate many megabytes of report data.
Specifies the directory to generate the report into.
Specifies the name to use for the project in the generated report.
Prints the version number of this instance of TorqueWrench and exits.
Sets the list of enabled warnings to those defined in warnings list. If not provided, a default set of warnings is enabled. The warnings list is a semicolon separated list of directives. Each directive is composed of a regular expression to match class names followed by a colon and a set of warnings. The set of warnings is a single string of mnemonics separated by commas. Each mnemonic can be prefixed with a + or a -. A prefix of + means the same thing as no prefix at all. Three special values, all, default, and none, can be used to enable all warnings, enable the default set of warnings, or disable all warnings, respectively.
For example, "com.stackframe.jvm.*:all,-wof;com.stackframe.*:all,-ucpc" would enable all warnings except wof in any class in the com.stackframe.jvm package and packages below it and all warnings except ucpc in all other packages.
TorqueWrench is compatible with the Ant build tool. An adapter class which defines an Ant task is provided in the TorqueWrench JAR file. The adapter class is named com.stackframe.tw.AntAdapter and can be found in $TW_HOME/torquewrench.jar. This task takes a nested element, which is a FileSet of JAR, WAR, EAR, RAR, and .class files to analyze.
The task accepts an optional attribute, outputDir, which is the path of a directory to output the report to. The outputDir attribute defaults to TorqueWrenchReport in the directory that TorqueWrench is run from.
The task accepts an optional attribute, generateClassView, which is a boolean. Setting this to true enables generation of class view documents in the report.
The task accepts an optional nested element, param. Each instance of this element takes two attributes named "name" and "value". Using these elements, options can be passed to warnings.
The task accepts an optional nested element, warn, which contains attributes indicating a list of warnings to enable or disable. Multiple instances of the warn element can be provided. Each instance of this element takes two attributes named "classes" and "warnings". The classes attribute is a regular expression indicating the classes to change the warnings for. The warnings attribute is a single string of mnemonics separated by commas. Each mnemonic can be prefixed with a + or a -. A prefix of + means the same thing as no prefix at all. Three special values, all, default, and none, can be used to enable all warnings, enable the default set of warnings, or disable all warnings, respectively. If no warn element is provided, all warnings are activated for all classes.
In the following example, osenv is used as the prefix for environment variables and the torquewrench task will only be defined and executed if the TW_HOME environment variable is set, making it easy to use the build file on machines that don't have TorqueWrench installed. The example also makes use of the warn attribute to enable all warnings except wof in any class in the com.stackframe.jvm package and packages below it and all warnings except ucpc in all other packages.
<property environment="osenv"/>
<target name="torquewrench" if="osenv.TW_HOME">
<taskdef name="torquewrench" classname="com.stackframe.tw.AntAdapter"
classpath="${osenv.TW_HOME}/torquewrench.jar" />
<torquewrench outputDir="TorqueWrench">
<warn classes="com.stackframe.jvm.*" warnings="all,-wof" />
<warn classes="com.stackframe.*" warnings="all,-ucpc" />
<fileset dir="bin" includes="**/*.jar" />
</torquewrench>
</target>
TorqueWrench generates its report into the directory specified by outputDir. This report is generated into several HTML files and an XML file. The XML file can be used to provide input into other tools or for long term metrics collection. The schema for the XML file is delivered in the $TW_HOME/schemas directory in DTD, XML Schema, and RELAX NG formats.
TorqueWrench gets more information about the classes it is warning about if it has the classes that those classes depend on. Adding in the classes that your code depends on (including even the JRE) will improve the quality of the reports.
Compiling your code with debug information (e.g. passing -g to javac) will also improve the quality of the reports that TorqueWrench generates.
Not all warnings are enabled by default as some warnings would only be useful for certain types of projects. If no warnings are specified, then the default set used is acsi, aibc, assu, bci, ccd, cdnp, cifp, cmec, cnsc, cnvc, ctcn, dcic, dcnc, dupm, eccc, efnm, ehse, ehsm, encc, envt, ewhc, fesc, fini, fmnp, fpr, hcwe, icss, ieon, iisl, imsc, lvao, mcce, mllc, mois, npec, oafc, pif, psf, rvi, sacf, saif, salv, sbdc, sec, sgcc, snvc, ssci, stsi, svci, svwm, tri, ucpc, unlv, unv, uuf, uum, vmss, wof, wolv.
The following is a complete list of warnings that TorqueWrench can report. For each warning, a three or four letter mnemonic is provided in parentheses which can be used in the warnings list when invoking TorqueWrench to enable or disable specific warnings.
This warning is triggered by a public class that is marked abstract, but that defines no concrete implementations for any methods. Such classes should probably be designed as interfaces so as to maximize the flexibility of the clients when defining implementations.
This warning is triggered by code that catches ArrayIndexOutOfBoundsException.
An example of a class that triggers this warning is:
public class aibc {
private String[] names = new String[] { "bob", "sally", "fred" };
public String foo() {
try {
return names[4];
} catch (ArrayIndexOutOfBoundsException e) {
//ignoring the exception
return null;
}
}
}
This warning is triggered by code that uses the word assert as a method, field, local variable name, or a component in a package name. As of Java 1.4, assert is a keyword. This warning is useful for projects that are currently using a pre-1.4 compiler and want to ensure that they can upgrade in the future.
This warning is triggered by calls to the constructor for Boolean. It is usually a better idea to use the Boolean.valueOf() method instead.
An example of a class that would trigger this warning is:
public class bci {
public Boolean foo() {
return new Boolean("true");
}
}
A better idea would be to use Boolean.valueOf() instead:
public class bci {
public Boolean foo() {
return Boolean.valueOf("true");
}
}
The "constant interface pattern" is the pattern of putting just constants into an interface class so that a client class can implement the class and avoid having to prefix the constants. This pattern should be avoided as it abuses the purpose of interfaces.
This warning is emitted when a class is encountered whose name begins with a lower case letter instead of an upper case letter. This warning ensures that standard practice for class names is followed. Because this is a matter of style, this warning is not enabled by default.
This warning is triggered by a class that does not have the public void constructor necessary as defined by its superclass or superinterface. This warning takes an option, classes, which can be used to customize the set of classes that TorqueWrench warns about. classes is intended for you to specify classes that are defined by your project as requiring that subclasses or implementing classes provide a void constructor.
| name | type | default | description |
|---|---|---|---|
classes | String | null |
A comma separated list of project specific classes. |
This warning is triggered by a non-final class that implements Cloneable and overrides the clone() method but that does not call super.clone().
This warning is triggered by a class that implements Cloneable but that does not promote the clone() method to public visibility.
This warning is triggered by a class that implements Cloneable and overrides the clone() method without removing CloneNotSupportedException from the list of checked exceptions.
This warning is triggered by code that catches ConcurrentModificationException.
This warning is triggered by code with the covariant compareTo() method defined.
This warning is triggered by a class that defines a clone() method but does not implement Cloneable.
This warning is triggered by code that implements the compareTo() method defined by the Comparable interface, but does not actually implement Comparable.
Classes which define the equals() method should also define the hashCode() method. Failing to do so can cause difficult to diagnose run-time errors if instances of the class are used as keys to a HashMap or added to a HashSet.
This warning is emitted when a class defines the hashCode() method, but not the equals() method.
This warning is triggered by the existence of two methods in a class that do the exact same thing.
| name | type | default | description |
|---|---|---|---|
max | int | 12 |
The threshold at which the warning will be triggered. Duplicate code chunks bigger than this value will trigger the warning. |
This warning is triggered by a finalize() method that does nothing.
Any publically constructable exception class should provide at least one constructor that supports exception chaining.
This warning is triggered by an exception handler that silently swallows an exception. It is preferred to do something with the exception, even if that is just logging it or rethrowing it as a RuntimeException or an AssertionError. For example, TorqueWrench will warn about the following method:
private void openFile(String fileName) {
try {
new FileInputStream(fileName);
} catch (FileNotFoundException fnfe) {
// This can't happen as fileName is checked before this method is called.
}
}
This could be easily replaced with code which does not silently fail:
private void openFile(String fileName) {
try {
new FileInputStream(fileName);
} catch (FileNotFoundException fnfe) {
// This can't happen as fileName is checked before this method is called.
throw new AssertionError(fnfe);
}
}
This warning is triggered by a class that implements Externalizable, but that defines readObject() and writeObject(), which are methods used by Serializable and are superceded by Externalizable. Such definitions usually indicate confusion about how Externalizable works.
This warning is triggered if a class defines a field that is also defined in a superclass. This is often a case of the two classes evolving without regard for one another.
This warning is emitted when a field is encountered that begins with an upper case letter instead of a lower case letter. This warning ensures that standard practice for naming of fields is followed. Because this is a matter of style, this warning is not enabled by default.
This warning is triggered by code that implements finalization by defining a finalize() method. Implementations of CLDC 1.0 do not support object finalization and this warning can be used to ensure that code can be used on such implementations. See sections 4.2 and 5.2.5 of CLDC 1.0a for more details.
This warning is triggered by code that invokes the finalize() method. The finalize() method should only be invoked once and it should only be invoked by the garbage collector.
An example of a class that triggers this warning is:
public class fini {
public void foo() throws Throwable {
finalize();
}
}
This warning is triggered by a class that overrides the finalize() method and gives it visibility other than protected. finalize() should be marked protected as it should only be called by subclasses and by the garbage collector.
This warning is triggered by code that uses floating point in some way. Implementations of CLDC 1.0 do not support floating point and this warning can be used to ensure that code can be used on such implementations. See sections 4.1 and 5.1 of CLDC 1.0a for more details.
This warning is triggered by code that references forbidden packages. Default examples of forbidden packages are sun.* and com.sun.*. Referencing these directly is not good code practice because these packages are part of the implementation and can be different across platforms and can change at anytime without notice.
| name | type | default | description |
|---|---|---|---|
packages | String | sun.*,com.sun.* |
The list of forbidden packages. |
This warning is triggered by code that catches IllegalMonitorStateException.
This warning is triggered by the existence of an inner class that could be marked as static because it does not use a reference to the enclosing class.
This warning is triggered by code that passes an explicit null parameter to the equals() method.
This warning is triggered by code that calls intern() on a String literal. String literal values are already in the intern pool and such usage indicates a misunderstanding of how String.intern() works.
This warning is triggered by code that overwrites a local variable without ever reading it.
This warning is triggered by methods that have a cyclomatic complexity exceeding the defined threshold.
| name | type | default | description |
|---|---|---|---|
max | int | 15 |
The threshold at which the warning will be triggered. Any value higher than this value will trigger the warning. |
Classes should define public methods in terms of abstract types or interfaces instead of with concrete implementations.
An example of a class that would trigger this warning is:
import java.util.ArrayList;
public class Sensor {
private final ArrayList targets = new ArrayList();
public void addTarget(Target target) {
targets.add(target);
}
public ArrayList getTargets() {
return targets;
}
}
This class triggers the warning because it is exposing a concrete Collection class, ArrayList, instead of an interface such as java.util.List or java.util.Collection. If the class were rewritten to expose only abstract types, it would not trigger the warning:
import java.util.List;
import java.util.ArrayList;
public class Sensor {
private final List targets = new ArrayList();
public void addTarget(Target target) {
targets.add(target);
}
public List getTargets() {
return targets;
}
}
Fields and methods should not be publically visible if they expose a type that is itself not publically visible. A special exception is made in this warning to account for interfaces as methods defined to implement an interface must be public. This warning is susceptible to generating false positives for implementations of interfaces that are not visible to it. If you receive a false positive for this warning, ensure that the class that defines the type involved is being provided to TorqueWrench.
This warning is emitted when a method is encountered that has the same name as a constructor. This is often a case of the developer accidentally improperly defining the constructor.
This warning is emitted when a method is encountered whose name begins with an upper case letter instead of a lower case letter. This warning ensures that standard practice for method names is followed. Because this is a matter of style, this warning is not enabled by default.
This warning is triggered by methods that do nothing but call their super() method, providing no extra value.
This warning is triggered by a method that is declared as returning an array and returns null instead a zero-length array. Returning a zero-length array can simplify code that calls such methods and can prevent null pointer exceptions. This warning is disabled by default because it can be considered a matter of style whether or not to enforce this rule.
This warning is triggered by code that catches NullPointerException.
This warning is triggered by code the allocates an object just to call getClass() on it. Such code should use the .class syntax.
This warning is triggered by the existence of non-final public instance fields in a public class. Such fields break encapsulation and should be avoided.
This warning is triggered by the existence of non-final public static fields in a public class. Such fields are in effect global variables and should be avoided.
This warning is triggered by code that ignores the return value of a method.
This warning is triggered by code that does a self-assignment of a class field. This is most often caused by a typo or misuse of copied code.
This warning is triggered by code that does a self-assignment of an instance field. This is most often caused by a typo or misuse of copied code.
This warning is triggered by code that does a self-assignment of a local variable. This is most often caused by a typo, misuse of copied code, or duplication of the functionality of Math.min() or Math.max().
This warning is triggered by a class which has no serialVersionUID field. Having a serialVersionUID field is necessary to support compatibility of serialized versions of objects with classes whose signatures have changed. Because most projects only use serialization for short-term storage and thus do not need such compatibility, this warning is disabled by default.
This warning is triggered by a class which implements Serializable and whose superclass does not implement Serializable and has no void constructor. Such a class will cause an InvalidClassException to be thrown if an attempt is made to serialize it.
This warning is triggered by a class which implements Serializable and has a field which is neither transient nor Serializable. Such a class will cause a NotSerializableException to be thrown if an attempt is made to serialize it. This warning is not enabled by default because it can generate false positives.
This warning is triggered by a class which has a serialVersionUID field but does not mark it as static final and make it a long.
This warning is triggered by code that invokes the String void constructor. Such code can be replaced with a reference to the empty String, "", which is guaranteed to be interned.
This warning is triggered by code that uses the String(String) constructor.
This warning is triggered by code that calls the toString() method on String objects.
An example of a class that triggers this warning is:
public class stsi {
public String foo() {
String text = getClass().getName();
return text.toString();
}
}
This warning is triggered by any call to a method on String that converts to or from a byte array using the default character set. Any code that wants to interface to a byte representation of a String in a portable way should use a method that specifies the desired character set.
This warning is triggered by a switch statement that has no default case or a default case that does nothing.
This warning is triggered by any call to System.exit() or Runtime.exit() with the exception of methods that match the main entry point (i.e. static void main(String[] args)) defined by Java.
This warning is triggered by any call to System.gc() or Runtime.gc().
This warning is triggered by code that calls the run() method on a Thread object. Only the JVM should be calling Thread.run() in response to a call to Thread.start(). This usually indicates confusion about how threads work.
This warning is triggered by a class that specifies unnecessary visibility for a method or constructor.
An example of a class that would trigger this warning is:
public abstract class Widget {
private final String name;
/**
* Construct a new Widget.
*
* @param name the name of the Widget
*/
public Widget(String name) {
this.name = name;
}
/**
* Draw the widget.
*/
public abstract void draw();
}
The Widget class is marked abstract and thus cannot be instantiated directly. Because only subclasses can invoke the constructor, it should be marked protected instead of public.
| name | type | default | description |
|---|---|---|---|
defaultConstructor | boolean | false |
Set to |
This warning is triggered by the existence of an unused field.
This warning is triggered by the existence of an unused local variable.
This warning is triggered by the existence of an unused method.
A utility class is a class that defines no virtual methods, only static methods. Such a class should have a single private constructor so as to prevent a client from instantiating it. This way, if the class does later on get a non-default constructor, no client code will be broken.
This warning is triggered by a virtual method that never makes use of the this reference. Such methods should be marked static.
This warning is triggered by the existence of fields that are written to, but never read from. This is often caused by the removal of code without checking that all dependent code is removed or by a local variable eclipsing a field.
This warning is triggered by the existence of a variable that is written to, but never read from. This is usually caused by code that has been incompletely modified but sometimes indicates the developer is incorrectly trying to pass values back through parameters.
An example of a method that would trigger this warning is:
public double linear(double x, double m, double b) {
//The z variable is never read from
int z = 4;
return m * x + b;
}
All support requests should be sent via email to torquewrench@stackframe.com or by calling +1 321.234.1428.
TorqueWrench is a trademark of StackFrame, LLC.
Java is a registered trademark of Sun Microsystems, Inc. in the United States, other countries, or both.
Windows is a trademark of Microsoft Corporation in the United States, other countries, or both.