Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

The

...

Java

...

language

...

annotation

...

facility

...

is

...

useful

...

for

...

documenting

...

design

...

intent

...

.

...

Source

...

code

...

annotation

...

is

...

a

...

mechanism

...

for

...

associating

...

metadata

...

with

...

a

...

program

...

element

...

and

...

making

...

it

...

available

...

to

...

the

...

compiler,

...

analyzers,

...

debuggers, or Java Virtual Machine (JVM) for examination. Several annotations are available for documenting thread-safety or the lack thereof.

Obtaining Concurrency Annotations

Two sets of concurrency annotations are freely available and licensed for use in any code. The first set consists of four annotations described in Java Concurrency in Practice (JCIP) [Goetz 2006], which can be downloaded from jcip.net (jar, javadoc, source). The JCIP annotations are released under the Creative Commons Attribution License.

The second, larger set of concurrency annotations is available from and supported by SureLogic. These annotations are released under the Apache Software License, Version 2.0 and can be downloaded via the Internet Archive at surelogic.com (jar, javadoc, source). The annotations can be verified by the SureLogic JSure tool, and they remain useful for documenting code even when the tool is unavailable. These annotations include the JCIP annotations because they are supported by the JSure tool. (JSure also supports use of the JCIP JAR file.)

To use the annotations, download and add one or both of the aforementioned JAR files to the code's build path. The use of these annotations to document thread-safety is descr

Warning
titleDeprecated Examples

These examples are based on SureLogic, as of 2010. The intent is still useful but the implementation is no longer supported.  We recommend using an annotation package that still enjoys active support.

Documenting Intended Thread-Safety

JCIP provides three class-level annotations to describe the programmer's design intent with respect to thread-safety.

The @ThreadSafe annotation is applied to a class to indicate that it is thread-safe. This means that no sequences of accesses (reads and writes to public fields, calls to public methods) can leave the object in an inconsistent state, regardless of the interleaving of these accesses by the runtime or any external synchronization or coordination on the part of the caller.

For example, the following Aircraft class specifies that it is thread-safe as part of its locking policy documentation. This class protects the x and y fields using a reentrant lock.

Code Block
bgColor#ccccff
 @ThreadSafe
 @Region("private AircraftState")
 @RegionLock("StateLock is stateLock protects AircraftState")
 public final class Aircraft {
   private final Lock stateLock = new ReentrantLock();
   // ...
   @InRegion("AircraftState")
   private long x, y;
   // ...
   public void setPosition(long x, long y) {
     stateLock.lock();
     try {
       this.x = x;
       this.y = y;
     } finally {
       stateLock.unlock();
     }
   }
   // ...
 }

The @Region and @RegionLock annotations document the locking policy upon which the promise of thread-safety is predicated.

Even when one or more @RegionLock or @GuardedBy annotations have been used to document the locking policy of a class, the @ThreadSafe annotation provides an intuitive way for reviewers to learn that the class is thread-safe.

The @Immutable annotation is applied to immutable classes. Immutable objects are inherently thread-safe; once they are fully constructed, they may be published via a reference and shared safely among multiple threads.

The following example shows an immutable Point class:

Code Block
bgColor#ccccff
 @Immutable
 public final class Point {
   private final int f_x;
   private final int f_y;

   public Point(int x, int y) {
     f_x = x;
     f_y = y;
   }

   public int getX() {
     return f_x;
   }

   public int getY() {
     return f_y;
   }
 }

According to Joshua Bloch [Bloch 2008],

It is not necessary to document the immutability of enum types. Unless it is obvious from the return type, static factories must document the thread safety of the returned object, as demonstrated by Collections.synchronizedMap.

The @NotThreadSafe annotation is applied to classes that are not thread-safe. Many classes fail to document whether they are safe for multithreaded use. Consequently, a programmer has no easy way to determine whether the class is thread-safe. This annotation provides clear indication of the class's lack of thread-safety.

For example, most of the collection implementations provided in java.util are not thread-safe. The class java.util.ArrayList could document this as follows:

Code Block
bgColor#ccccff
 package java.util.ArrayList;

 @NotThreadSafe
 public class ArrayList<E> extends ... { or the VM for examination. Several annotations are available for documenting thread-safety, or the lack thereof.

h2. Obtaining Concurrency Annotations

There are two sets of concurrency annotations that are freely available and licensed for use in any code. The first set consists of four annotations described in _Java Concurrency in Practice_ (JCIP)  \[[Goetz 06|AA. Java References#Goetz 06]\] which can be downloaded from [jcip.net|http://www.jcip.net] ([jar|http://jcip.net/jcip-annotations.jar], [javadoc|http://jcip.net/annotations/doc/index.html], [source|http://jcip.net/jcip-annotations-src.jar]). The JCIP annotations are released under the [Creative Commons Attribution License|http://creativecommons.org/licenses/by/2.5].

The second, larger, set of concurrency annotations is available from and supported by [SureLogic|http://www.surelogic.com]. The SureLogic annotations are released under [The Apache Software License, Version 2.0|http://www.apache.org/licenses/LICENSE-2.0] and can be downloaded from [surelogic.com|http://surelogic.com/promises/index.html] ([jar|http://surelogic.com/promises/jars/], [javadoc|http://surelogic.com/promises/apidocs/index.html], [source|http://surelogic.com/promises/source-repository.html]). These annotations can be verified by the [SureLogic|http://www.surelogic.com] [JSure|http://www.surelogic.com/concurrency-tools.html] tool and are useful for documenting code even if the tool is unavailable.  The [SureLogic|http://www.surelogic.com] annotations also include the JCIP annotations because they are supported by the JSure tool (JSure also supports use of the JCIP Jar file).

To use the annotations, download and add one or both of the aforementioned Jar files to the code's build path. The use of these annotations to document thread-safety is discussed below.

h2. Documenting Intended Thread-safety

JCIP provides three class-level annotations to describe the programmer's design intent with respect to thread-safety. 

The [@ThreadSafe|http://surelogic.com/promises/apidocs/com/surelogic/ThreadSafe.html] annotation is applied to a class to indicate that it is [thread-safe|BB. Definitions#thread-safe]. This means that no sequences of accesses (reads and writes to public fields, calls to public methods) can leave the object in an inconsistent state, regardless of the interleaving of these accesses by the runtime or any external synchronization or coordination on part of the caller.

For example, the {{Aircraft}} class shown below specifies that it is thread-safe as part of its locking policy documentation. This class protects the {{x}} and {{y}} fields using a {{java.util.concurrent.locks.ReentrantLock}}. 

{code:bgColor=#ccccff}
 @ThreadSafe
 @Region("private AircraftState")
 @RegionLock("StateLock is stateLock protects AircraftState")
 public final class Aircraft {
   private final Lock stateLock = new ReentrantLock();
   // ...
   @InRegion("AircraftState")
   private long x, y;
   // ...
   public void setPosition(long x, long y) {
     stateLock.lock();
     try {
       this.x = x;
       this.y = y;
     } finally {
       stateLock.unlock();
     }
   }
   // ...
 }
{code}

The [@Region|http://surelogic.com/promises/apidocs/com/surelogic/Region.html] and [@RegionLock|http://surelogic.com/promises/apidocs/com/surelogic/RegionLock.html] annotations document the precise locking policy that the promise of thread-safety is predicated upon.

Even if one or more [@RegionLock|http://surelogic.com/promises/apidocs/com/surelogic/RegionLock.html] or [@GuardedBy|http://jcip.net/annotations/doc/net/jcip/annotations/GuardedBy.html] annotations have been used to document the locking policy of a class, the [@ThreadSafe|http://surelogic.com/promises/apidocs/com/surelogic/ThreadSafe.html] annotation provides an intuitive way for reviewers to learn that the class is thread-safe.

[@Immutable|http://surelogic.com/promises/apidocs/com/surelogic/Immutable.html]: This annotation is applied to [immutable|BB. Definitions#immutable] classes. Immutable objects are inherently thread-safe; they may be safely shared amongst multiple threads after they are fully constructed, and published by declaring the corresponding reference as volatile.

The following example shows an immutable {{Point}} class:

{code:bgColor=#ccccff}
 @Immutable
 public final class Point {
   private final int f_x;
   private final int f_y;
 
   public Point(int x, int y) {
     f_x = x;
     f_y = y;
   }
 
   public int getX() {
     return f_x;
   }
 
   public int getY() {
     return f_y;
   }
 }
{code}

"It is not necessary to document the immutability of {{enum}} types. Unless it is obvious from the return type, static factories must document the thread safety of the returned object, as demonstrated by {{Collections.synchronizedMap}}." \[[Bloch 08|AA. Java References#Bloch 08]\].

[@NotThreadSafe|http://surelogic.com/promises/apidocs/com/surelogic/NotThreadSafe.html] This annotation is applied to classes that are not thread-safe. Several classes do not document whether they are safe for multithreaded use or not. Consequently, a programmer has no easy way to determine whether the class is thread-safe. This annotation provides clear indication of the class's lack of thread-safety.

For example, most of the collection implementations provided in {{java.util}} are not thread-safe. The class {{java.util.ArrayList}} which is not thread-safe could document this as shown below.

{code:bgColor=#ccccff}
 package java.util;
 
 @NotThreadSafe
 public class ArrayList<E> extends ... {
   // ...
 }
{code}

h2. Documenting Locking Policies

According to Goetz et al. \[[Goetz 06, pg 28|AA. Java References#Goetz 06]\]:

{quote}
For each mutable state variable that may be accessed by more than one thread, _all_ accesses to that variable must be performed with the _same_ lock held. In this case, we say that the variable is _guarded by_ that lock.
{quote}

Consequently, it is important to document all the locks that are being used to protect shared state. JCIP provides the [@GuardedBy|http://jcip.net/annotations/doc/net/jcip/annotations/GuardedBy.html] annotation for this purpose while SureLogic provides the [@RegionLock|http://surelogic.com/promises/apidocs/com/surelogic/RegionLock.html] annotation. 

[@GuardedBy|http://jcip.net/annotations/doc/net/jcip/annotations/GuardedBy.html]: The field or method to which this annotation is applied can only be accessed when holding a particular lock, which may be an intrinsic lock, or a dynamic lock such as {{java.util.concurrent.Lock}}.

For example, the following {{MovablePoint}} class implements a movable point which has the capability of remembering its past locations using an array list, {{memo}}.

{code:bgColor=#ccccff}
@ThreadSafe
public final class MovablePoint {
 
  @GuardedBy("this") double xPos = 1.0;
  @GuardedBy("this") double yPos = 1.0;
  @GuardedBy("itself") static final List<MovablePoint> memo = new ArrayList<MovablePoint>();
 
  public void move(double slope, double distance) {
    synchronized (this) {
      rememberPoint(this);
      xPos += (1 / slope) * distance;
      yPos += slope * distance;
    }
  }

  public static void rememberPoint(MovablePoint value) {
    synchronized (memo) {
      memo.add(value);
    }
  }
}
{code}
The [@GuardedBy|http://jcip.net/annotations/doc/net/jcip/annotations/GuardedBy.html] annotations on the {{xPos}} and {{yPos}} fields indicate that access to these fields is protected by holding a lock on {{this}} (as is done in the {{move()}} method which mutates these fields).  The [@GuardedBy|http://jcip.net/annotations/doc/net/jcip/annotations/GuardedBy.html] annotation on the {{memo}} list indicates that a lock on the {{ArrayList}} object protects its contents (as is done in the {{rememberPoint()}} method).

One issue with the [@GuardedBy|http://jcip.net/annotations/doc/net/jcip/annotations/GuardedBy.html] annotation is that it does not clarify that there is a relationship between the two fields in the above example. This limitation can be overcome by using the SureLogic [@RegionLock|http://surelogic.com/promises/apidocs/com/surelogic/RegionLock.html] annotation.

[@RegionLock|http://surelogic.com/promises/apidocs/com/surelogic/RegionLock.html]: Declares a new region lock for the class to which this annotation is applied. This declaration creates a new named lock that associates a particular lock object with a region of the class. The region may only be accessed when the lock is held.

For example, the {{SimpleLock}} locking policy indicates that synchronizing on the instance protects all of the instance's state:

{code:bgColor=#ccccff}
 @RegionLock("SimpleLock is this protects Instance")
 class Simple { ... }
{code}

Unlike [@GuardedBy|http://jcip.net/annotations/doc/net/jcip/annotations/GuardedBy.html], the [@RegionLock|http://surelogic.com/promises/apidocs/com/surelogic/RegionLock.html] annotation allows the programmer to give an explicit, and hopefully meaningful, name to the locking policy.
 
In addition to naming the locking policy, the [@Region|http://surelogic.com/promises/apidocs/com/surelogic/Region.html] annotation allows a name to be given to the region of the state that is being protected. This makes it clear that the state _belongs together_ with respect to the locking policy. This is demonstrated in the following example:

{code:bgColor=#ccccff}
 @Region("private AircraftPosition")
 @RegionLock("StateLock is stateLock protects AircraftPosition")
 public final class Aircraft {
   private final Lock stateLock = new ReentrantLock();

   @InRegion("AircraftPosition")
   private long x, y;

   @InRegion("AircraftPosition")
   private long altitude;
   // ...
   public void setPosition(long x, long y) {
     stateLock.lock();
     try {
       this.x = x;
       this.y = y;
     } finally {
       stateLock.unlock();
     }
   }
   // ...
 }
{code}

In this example, a locking policy named {{StateLock}} is used to indicate that locking on {{stateLock}} protects the named region, {{AircraftPosition}}, which includes the mutable state used to represent the position of the aircraft.

h4. Construction of mutable objects

Typically, object construction is considered an exception to the locking policy because objects are thread-confined when they are created. An object is confined to the thread that uses the {{new}} operator to create its instance. After creation, the object can be safely published to other threads. However, the object is not shared until the thread that created the instance allows it to be shared. Safe publication approaches discussed in [CON14-J. Do not let the "this" reference escape during object construction] can be succinctly expressed with the [@Unique("return")|http://surelogic.com/promises/apidocs/com/surelogic/Unique.html] annotation.

For example, in the code shown below, the [@Unique("return")|http://surelogic.com/promises/apidocs/com/surelogic/Unique.html] annotation documents that the object returned from the constructor is a unique reference. {mc} This looks suspicious...constructor returning objects? {mc}

{code:bgColor=#ccccff}
 @RegionLock("Lock is this protects Instance")
 public final class Example {
   private int x = 1;
   private int y;
 
   @Unique("return")
   public Example(int y) {
     this.y = y;
   }
   // ...
 }
{code}


h2. Documenting thread-confinement policies

Sutherland and Scherlis \[[Sutherland 10|AA. Java References#Sutherland 10]\] propose annotations that can document thread-confinement policies. Their approach is designed to allow verification of the annotations against code as it exists.

For example, to express the design intent that a program has at most one _AWT_ event dispatch thread, several _Compute_ threads, and the _Compute_ threads are forbidden to handle AWT data structures or events, use the following annotations:

{code:bgColor=#ccccff}
@ColorDeclare AWT, Compute
@IncompatibleColors AWT, Compute
@MaxColorCount AWT 1
{code}


h2. Documenting wait-notify protocols

"A state-dependent class should either fully expose (and document) its waiting and notification protocols to subclasses, or prevent subclasses from participating in them at all. (This is an extension of "design and document for inheritance, or else prohibit it" \[EJ Item 15\].) At the very least, designing a state-dependent class for inheritance requires exposing the condition queues and locks and documenting the condition predicates and synchronization policy; it may also require exposing the underlying state variables. (The worst thing a state-dependent class can do is expose its state to subclasses but not document its protocols for waiting and notification; this is like a class exposing its state variables but not documenting its invariants.)". \[[Goetz 06, pg 395|AA. Java References#Goetz 06]\]

Wait-notify protocols should be adequately documented. Currently, we are not aware of any annotations for this purpose.


h2. Risk Assessment

Failing to document thread-safety and not annotating concurrent code can make detection and prevention of race conditions and data races relatively difficult.


|| Rule || Severity || Likelihood || Remediation Cost || Priority || Level ||
| CON33\- J | low | probable | medium | {color:green}{*}P4{*}{color} | {color:green}{*}L2{*}{color} |


h3. Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the [CERT website|https://www.kb.cert.org/vulnotes/bymetric?searchview&query=FIELD+KEYWORDS+contains+CON33-J].

h2. References

\[[Bloch 08|AA. Java References#Bloch 08]\] Item 70: "Document thread safety"
\[[Goetz 06|AA. Java References#Goetz 06]\] 
\[[Sutherland 10|AA. Java References#Sutherland 10]\]

----
[!The CERT Sun Microsystems Secure Coding Standard for Java^button_arrow_left.png!|CON32-J. Synchronize access to static fields that may be modified by untrusted code]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[!The CERT Sun Microsystems Secure Coding Standard for Java^button_arrow_up.png!|11. Concurrency (CON)]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[!The CERT Sun Microsystems Secure Coding Standard for Java^button_arrow_right.png!|CON34-J. Do not use an instance lock to protect shared static data]

Documenting Locking Policies

It is important to document all the locks that are being used to protect shared state. According to Brian Goetz and colleagues [Goetz 2006],

For each mutable state variable that may be accessed by more than one thread, all accesses to that variable must be performed with the same lock held. In this case, we say that the variable is guarded by that lock. (p. 28)

JCIP provides the @GuardedBy annotation for this purpose, and SureLogic provides the @RegionLock annotation. The field or method to which the @GuardedBy annotation is applied can be accessed only when holding a particular lock. It may be an intrinsic lock or a dynamic lock such as java.util.concurrent.Lock.

For example, the following MovablePoint class implements a movable point that can remember its past locations using the memo array list:

Code Block
bgColor#ccccff
@ThreadSafe
public final class MovablePoint {

  @GuardedBy("this")
  double xPos = 1.0;
  @GuardedBy("this")
  double yPos = 1.0;
  @GuardedBy("itself")
  static final List<MovablePoint> memo
    = new ArrayList<MovablePoint>();

  public void move(double slope, double distance) {
    synchronized (this) {
      rememberPoint(this);
      xPos += (1 / slope) * distance;
      yPos += slope * distance;
    }
  }

  public static void rememberPoint(MovablePoint value) {
    synchronized (memo) {
      memo.add(value);
    }
  }
}

The @GuardedBy annotations on the xPos and yPos fields indicate that access to these fields is protected by holding a lock on this. The move() method also synchronizes on this, which modifies these fields. The @GuardedBy annotation on the memo list indicates that a lock on the ArrayList object protects its contents. The rememberPoint() method also synchronizes on the memo list.

One issue with the @GuardedBy annotation is that it fails to indicate when there is a relationship between the fields of a class. This limitation can be overcome by using the SureLogic @RegionLock annotation, which declares a new region lock for the class to which this annotation is applied. This declaration creates a new named lock that associates a particular lock object with a region of the class. The region may be accessed only when the lock is held. For example, the SimpleLock locking policy indicates that synchronizing on the instance protects all of its state:

Code Block
bgColor#ccccff
 @RegionLock("SimpleLock is this protects Instance")
 class Simple { ... }

Unlike @GuardedBy, the @RegionLock annotation allows the programmer to give an explicit, and hopefully meaningful, name to the locking policy.

In addition to naming the locking policy, the @Region annotation allows a name to be given to the region of the state that is being protected. That name makes it clear that the state and locking policy belong together, as demonstrated in the following example:

Code Block
bgColor#ccccff
 @Region("private AircraftPosition")
 @RegionLock("StateLock is stateLock protects AircraftPosition")
 public final class Aircraft {
   private final Lock stateLock = new ReentrantLock();

   @InRegion("AircraftPosition")
   private long x, y;

   @InRegion("AircraftPosition")
   private long altitude;
   // ...
   public void setPosition(long x, long y) {
     stateLock.lock();
     try {
       this.x = x;
       this.y = y;
     } finally {
       stateLock.unlock();
     }
   }
   // ...
 }

In this example, a locking policy named StateLock is used to indicate that locking on stateLock protects the named AircraftPosition region, which includes the mutable state used to represent the position of the aircraft.

Construction of Mutable Objects

Typically, object construction is considered an exception to the locking policy because objects are thread-confined when they are created. An object is confined to the thread that uses the new operator to create its instance. After creation, the object can be published to other threads safely. However, the object is not shared until the thread that created the instance allows it to be shared. Safe publication approaches discussed in TSM01-J. Do not let the this reference escape during object construction can be expressed succinctly with the @Unique("return") annotation.

For example, in the following code, the @Unique("return") annotation documents that the object returned from the constructor is a unique reference:

Code Block
bgColor#ccccff
 @RegionLock("Lock is this protects Instance")
 public final class Example {
   private int x = 1;
   private int y;

   @Unique("return")
   public Example(int y) {
     this.y = y;
   }
   // ...
 }

Documenting Thread-Confinement Policies

Dean Sutherland and William Scherlis propose annotations that can document thread-confinement policies. Their approach allows verification of the annotations against as-written code [Sutherland 2010].

For example, the following annotations express the design intent that a program has, at most, one Abstract Window Toolkit (AWT) event dispatch thread and several compute threads, and that the compute threads are forbidden to handle AWT data structures or events:

Code Block
bgColor#ccccff
@ThreadRole AWT, Compute
@IncompatibleThreadRoles AWT, Compute
@MaxRoleCount AWT 1

Documenting Wait-Notify Protocols

According to Goetz and colleagues [Goetz 2006],

A state-dependent class should either fully expose (and document) its waiting and notification protocols to subclasses, or prevent subclasses from participating in them at all. (This is an extension of "design and document for inheritance, or else prohibit it" [EJ Item 15].) At the very least, designing a state-dependent class for inheritance requires exposing the condition queues and locks and documenting the condition predicates and synchronization policy; it may also require exposing the underlying state variables. (The worst thing a state-dependent class can do is expose its state to subclasses but not document its protocols for waiting and notification; this is like a class exposing its state variables but not documenting its invariants.) (p. 395)

Wait-notify protocols should be documented adequately. Currently, we are not aware of any annotations for this purpose.

Applicability

Annotating concurrent code helps document the design intent and can be used to automate the detection and prevention of race conditions and data races.

Automated Detection

Tool
Version
Checker
Description
The Checker Framework

2.1.3

GUI Effect CheckerEnsure that non-GUI threads do not access the UI which would crash the application (see Chapter 14)

Bibliography

[Bloch 2008]

Item 70, "Document Thread Safety"

[Goetz 2006]

Java Concurrency in Practice

[Sutherland 2010]

Composable Thread Coloring


...

Image Added Image Added Image Added