Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: changed the title and refined the description

A common error is to assume that shared references to immutable objects need not be synchronized. However, a correctly synchronized program must synchronize access to shared references.

Wiki Markup
The Java™ Programming Language, Fourth Edition \[[JPL 06|AA. Java References#JPL 06]\], "Section 14.10.2. Final Fields and Security" states:

... you can use final fields to define immutable objects. There is a common misconception that shared access to immutable objects does not require any synchronization because the state of the object never changes. This is a misconception in general because it relies on the assumption that a thread will be guaranteed to see the initialized state of the immutable object, and that need not be the case. The problem is that, while the shared object is immutable, the reference used to access the shared object is itself shared and often mutable. Consequently, a correctly synchronized program must synchronize access to that shared reference, but often programs do not do this, because programmers do not recognize the need to do it. For example, suppose one thread creates a String object and stores a reference to it in a static field. A second thread then uses that reference to access the string. There is no guarantee, based on what we've discussed so far, that the values written by the first thread when constructing the string will be seen by the second thread when it accesses the string.

It is not always the case that classes that use immutable objects are themselves immutable. Immutable objects are thread-safe, however, classes composed of immutable objects may not be unless this guideline is followed.

Noncompliant Code Example

This noncompliant code example publishes the helper field prematurely through the getHelper() method. Multiple threads may initialize the field, making class Foo mutable. consists of the immutable class Helper:

Code Block

// Immutable Helper
public class Helper
Code Block
bgColor#FFCCCC

class Foo {
  private Helperfinal int helpern;

  public Helper(int getHelper(n) {
    this.n return= helpern;
  }

  // ...
}

and a mutable class Foo:

Code Block
bgColor#FFCCCC

class Foo public void initialize(int num) {
  private Helper helper = new Helper(num);
  }
}

// Immutable Helper
public classHelper HelpergetHelper() {
  private final intreturn nhelper;
  }

  public void Helperinitialize(int nnum) {
    this.nhelper = nnew Helper(num);
  }
  // ...
}
}

The Foo.getHelper() method publishes the mutable helper field.

Because If the Helper class is immutable, it cannot be changed after it is initialized and will always be properly constructed. However, this does not prevent a thread from accessing is therefore thread-safe.

However, because the helper field of class Foo such that it misses observing the most recent value set by some other is not properly synchronized, it is possible that the Foo.getHelper() method will return a reference to a partially or incorrectly initialized helper object, if invoked from a separate thread.

Compliant Solution (synchronization)

This compliant solution synchronizes the methods of class Foo to ensure that no thread sees a partially initialized helper field.

Code Block
bgColor#CCCCFF
class Foo {
  private Helper helper;

  public synchronized Helper getHelper() {
    return helper;
  }

  public synchronized void initialize(int num) {
    helper = new Helper(num);
  }
}

The immutable Helper class is unchanged.

Compliant Solution (volatile)

Immutable members can be safely published by declaring them volatile as described in CON00-J. Know when to use volatileDeclare shared variables as volatile to ensure visibility and prevent reordering of accesses.

Code Block
bgColor#CCCCFF
class Foo {
  private volatile Helper helper;

  public synchronized Helper getHelper() {
    return helper;
  }

  public synchronized void initialize(int num) {
    helper = new Helper(num);
  }
}

The immutable Helper class is unchanged.

Risk Assessment

The assumption that classes containing immutable objects are immutable is misleading and can cause serious thread-safety issues.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

CON28-J

low

probable

medium

P4

L2

Automated Detection

TODO

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

References

Wiki Markup
\[[API 06|AA. Java References#API 06]\] 
\[[JPL 06|AA. Java References#JPL 06]\], 14.10.2. Final Fields and Security:

...