Versions Compared

Key

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

...

Synchronizing both methods guarantees that they cannot execute concurrently. If one thread were to call initialize() just before another thread calls called getHelper(), the synchronized initialize() method will would always finish first. The synchronized keywords establish a happens-before relationship between the two threads. Consequently, the thread calling getHelper() would see either the fully initialized Helper object or an absent Helper object (that is, helper would contain a null reference). This approach guarantees proper publication both for immutable and for mutable members.

...

The Java Memory Model guarantees that the fully-initialized values of fields that are declared final will be fully constructed before any reference to the containing object is made visibleare safely published to every thread that reads those values at some point no later than the end of the object's constructor.

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

  public Helper getHelper() {
    return helper;
  }

  public Foo() {
    // Point 1
    helper = new Helper(42);
    // Point 2
  }
}

...

Consequently, the reference to the helper instance should not be published before remain unpublished until the Foo class's constructor has finished its initializationcompleted. ( See rule TSM01-J. Do not let the (this) reference escape during object construction for additional information.)

Compliant Solution (Final Field and Thread-safe Composition)

...

The helper field is declared final to guarantee that the vector is always created before any accesses take place. It can be initialized safely by invoking the synchronized initialize() method, which ensures that only one Helper object is ever added to the vector. If getHelper() is is invoked before initialize(), it calls initializeThe getHelper() to avoid avoids the possibility of a null-pointer de-reference by the client. The getHelper() method does not require synchronization to simply return Helper, and, because the conditionally invoking initialize(). Although the isEmpty() call in getHelper() is made from an unsynchronized context (which permits multiple threads to decide that they must invoke initialize, race conditions that could result in addition of a second object to the vector are nevertheless impossible. The synchronized initialize() method also checks to make sure whether helper is empty before adding a new Helper object, there is no possibility of exploiting a race condition to add a second object to the vectorand at most one thread can execute initialize() at any time; consequently, only the first thread to execute initialize can ever see an empty vector. Consequently, the getHelper() method can safely omit any synchronization of its own.

Compliant Solution (Static Initialization)

In this compliant solution, the helper field is initialized statically initialized, ensuring that the object referenced by the field is fully initialized before its reference is becomes visible.

Code Block
bgColor#CCCCFF
// Immutable Foo
final class Foo {
  private static final Helper helper = new Helper(42);

  public static Helper getHelper() {
    return helper;
  }
}

Although not a requirement, the The helper field should be declared final to document the class's immutability.

...

This compliant solution requires that helper be declared volatile and that class Helper be immutable. If it were not immutablemutable, the code would violate rule VNA06-J. Do not assume that declaring a reference volatile guarantees visibility of the members of the referenced object, and additional synchronization would be necessary. (See ; see the next compliant solution for details. ) AndAdditionally, if the helper field were non-volatile, it would violate rule VNA01-J. Ensure visibility of shared references to immutable objects.

Similarly, Providing a public static factory method that returns a new instance of Helper can be provided in the Helper class Helper is both permitted and encouraged. This approach allows the Helper instance to be created in a private constructor.

Compliant Solution (Mutable Thread-safe Object, Volatile Reference)

If When Helper is mutable but thread-safe, it can be published safely by declaring the helper field in the Foo class volatile.

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

  public Helper getHelper() {
    return helper;
  }

  public void initialize() {
    helper = new Helper(42);
  }
}

// Mutable but thread-safe Helper
public class Helper {
  private volatile int n;
  private final Object lock = new Object();

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

  public void setN(int value) {
    synchronized (lock) {
      n = value;
    }
  }
}

Because the Helper object can change state after its construction, synchronization is necessary Synchronization is required to ensure the visibility of mutable members after initial publication . Consequently, because the Helper object can change state after its construction. This compliant solution synchronizes the setN() method is synchronized to provide guarantee the visibility of the n field in this compliant solution. ( See rule VNA06-J. Do not assume that declaring a reference volatile guarantees visibility of the members of the referenced object for additional information.)

If the Helper class is not was synchronized properlyincorrectly, declaring helper volatile in the Foo class class would guarantee only guarantees the visibility of the initial publication of Helper and not ; the visibility guarantee would exclude visibility of subsequent state changes. Consequently, volatile references alone are inadequate for publishing objects that are not thread-safe.

If the helper field in the Foo class is not declared volatile, the n field should be declared volatile so that to establish a happens-before relationship is established between the initialization of n and the write of Helper to the helper field. This is in compliance would comply with rule VNA06-J. Do not assume that declaring a reference volatile guarantees visibility of the members of the referenced object. This is required only when the caller (class Foo) cannot be trusted to declare helper volatile.

...

TSM03-EX1: Classes that prevent partially initialized objects from being used may publish partially initialized objects. This may could be implemented, for example, by setting a volatile boolean flag in the last statement of the initializing code and ensuring checking whether this flag is set before allowing class methods to execute.

...

This technique ensures that, even if in the event that a reference to the Helper object instance is were published before its initialization is overwas complete, the instance is unusable. The instance is would be unusable because every each method within Helper must check checks the flag to determine whether the initialization has finished.

Risk Assessment

Failing Failure to synchronize access to shared mutable data can cause different threads to observe different states of the object or to observe a partially-initialized object.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

TSM03-J

medium

probable

medium

P8

L2

Automated Detection

...

Related Vulnerabilities

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

...

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="6e68f386b4c70f76-0cece812-4fcd4af1-8c8490db-70a6682731d65e6891e434d5"><ac:plain-text-body><![CDATA[

[[API 2006

AA. Bibliography#API 06]]

 

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="5cbb1c632dfc6fd0-8ec56f17-458d4edc-ad3ab337-067577ee5cb769cd77e7ab70"><ac:plain-text-body><![CDATA[

[[Bloch 2001

AA. Bibliography#Bloch 01]]

Item 48: "Synchronize access to shared mutable data"

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="ab11487805f43808-7212562d-40864f75-ab71b418-fd2422fb6fb40d6cbec92a93"><ac:plain-text-body><![CDATA[

[[Goetz 2006

AA. Bibliography#Goetz 06]]

Section 3.5.3 "Safe Publication Idioms"

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="732c72b310871737-835b527b-467849ca-845ca15b-251e5962c368dc1ec75110df"><ac:plain-text-body><![CDATA[

[[Goetz 2007

AA. Bibliography#Goetz 07]]

Pattern #2: "one-time safe publication"

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="c4c19e61c81b7b51-0a5cce05-453c4e3a-81c1bf8f-3c1be9dc13d12c59f4bdfaf4"><ac:plain-text-body><![CDATA[

[[JPL 2006

AA. Bibliography#JPL 06]]

14.10.2. "Final Fields and Security"

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="e96f562e44ef6738-5d2f14ce-46874659-b31d88e9-03171fb936764f577238427b"><ac:plain-text-body><![CDATA[

[[Pugh 2004

AA. Bibliography#Pugh 04]]

 

]]></ac:plain-text-body></ac:structured-macro>

...