Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: s/effectively immutable/immutable/g;
Wiki Markup
According to the Java Language Specification \[[JLS 05|AA. Java References#JLS 05]\], section, 8.3.1.4 {{volatile}} Fields:
{quote}
A field may be declared {{volatile}}, in which case the Java memory model (§17) ensures that all threads see a consistent value for the variable.
{quote}

Notably, this applies only to fields and not to the contents of objects that are declared {{volatile}}. A thread may not observe a recent write to the object's field from another thread.

Declaring an object {{volatile}} in order to ensure visibility of the most up-to-date object state does not work without the use of explicit synchronization, unless the object is [effectively immutable|BB. Definitions#effectively immutableDefinitions#immutable].

In the absence of synchronization, the effect of declaring an object reference {{volatile}} is that when one thread sets the object to a new value, other threads can see the new reference immediately. If the object is immutable, this has the effect that other threads also see a consistent view of the state of the object. However, if the object is mutable and so, modified by a thread, other threads may see a partially-modified object, or an object in a (temporarily) inconsistent state \[[Goetz 07|AA. Java References#Goetz 07]\]. Declaring the object {{volatile}} does not prevent this issue.


h2. Noncompliant Code Example (Arrays)

This noncompliant code example shows an array object (arrays are objects in Java) that is declared {{volatile}}. It appears that when, a value is written by a thread to one of the array elements, it will be visible to other threads immediately. This is misleading because the {{volatile}} keyword just makes the array reference visible to all threads and does not affect the actual data contained within the array. 

{code:bgColor=#FFcccc}
volatile int[] arr = new int[20];
// ...
arr[1] = 10;
{code}

It is possible for one thread to set a new value to {{arr\[1\]}} while another thread attempts to read the value of {{arr\[1\]}}, with the result that the reading thread receives an inconsistent value for {{arr\[1\]}}.


h2. Compliant Solution ({{AtomicIntegerArray}})

This compliant solution suggests using the {{java.util.concurrent.atomic.AtomicIntegerArray}} concurrency utility. Using its {{set(index, value)}} method ensures that the write is atomic and the resulting value is immediately visible to other threads. The other threads can retrieve a value from a specific index by using the {{get(index)}} method.

{code:bgColor=#ccccff}
AtomicIntegerArray aia = new AtomicIntegerArray(5);
// ...
aia.set(1, 10);
{code}

h2. Noncompliant Code Example ({{Properties}} object)

This noncompliant code example declares an instance field of type {{Properties}} as {{volatile}}. The field can be mutated using the {{put()}} method.

{code:bgColor=#FFcccc}
class Foo {
  private volatile Properties properties;

  public Foo() {
    properties = new Properties();
    // Load some useful values into properties
  }

  public String get(String s) {
    return properties.getProperty(s);
  }

  public void put(String key, String value) {
    // Perform validation of value
    properties.setProperty(key, value);
  }
}
{code}

This class permits a race condition. If one thread calls {{get()}} while another calls {{put()}}, the first thread may receive a stale value, or an internally inconsistent value from the {{properties}} object. Declaring the object {{volatile}} does not prevent this data race.

Even if the client thread sees the new reference to {{properties}}, the object state that it observes may change in the meantime. {mc} The Java Memory Model does not guarantee that the {{properties}} field will have been properly initialized when it is necessary. ==Let's not talk about initialization here=={mc} Because the object is not immutable, it is unsafe for use in a multi-threaded environment.

h2. Compliant Solution (immutable)

This compliant solution renders the {{Foo}} class effectively immutable. Consequently, once it is properly constructed, no thread can modify {{properties}} and cause a race condition.

{code:bgColor=#ccccff}
class Foo {
  private final Properties properties;

  public Foo() {
    properties = new Properties();
    // Load some useful values into properties
  }

  public String get(String s) {
    return properties.getProperty(s);
  }
}
{code}

The drawback of this solution is that the {{put()}} method cannot be accommodated if the goal is to ensure immutability. The {{Foo}} and {{Properties}} classes are both effectively immutable. They are not truly class is [immutable|BB. Definitions#immutable] because the {{Properties}} class is not finalall of its fields are {{final}}.


h2. Compliant Solution (the cheap read-write lock trick)

This compliant solution uses explicit synchronization to ensure thread safety. It declares the object {{volatile}} to guard retrievals that use the getter method. A synchronized setter method is used to set the value of the {{Properties}} object. 

{code:bgColor=#ccccff}
public class Foo {
  private volatile Properties properties;

  public Foo() {
    properties = new Properties();
    // Load some useful values into properties
  }

  public String get(String s) {
    return properties.getProperty(s);
  }

  public synchronized void put(String key, String value) {
    // Perform validation of value
    properties.setProperty(key, value);
  }
}
{code}

This compliant solution has the advantage that it can accommodate the setter method. Declaring the object as {{volatile}} for safe publication using getter methods is cheaper in terms of performance, than declaring the getters as {{synchronized}}. However, synchronizing the setter methods is mandatory. 


h2. Risk Assessment

Failing to synchronize access to shared mutable data can cause different threads to observe different states of the object.

|| Rule || Severity || Likelihood || Remediation Cost || Priority || Level ||
| CON11-J | medium | probable | medium | {color:#cc9900}{*}P8{*}{color} | {color:#cc9900}{*}L2{*}{color} |

h3. Automated Detection

TODO

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+CON11-J].

h2. References

\[[Goetz 07|AA. Java References#Goetz 07]\] Pattern #2: "one-time safe publication"
\[[JLS 05|AA. Java References#JLS 05]\]

----
[!The CERT Sun Microsystems Secure Coding Standard for Java^button_arrow_left.png!|FIO36-J. Do not create multiple buffered wrappers on an InputStream]      [!The CERT Sun Microsystems Secure Coding Standard for Java^button_arrow_up.png!|09. Input Output (FIO)]      [!The CERT Sun Microsystems Secure Coding Standard for Java^button_arrow_right.png!|09. Input Output (FIO)]