...
A method declared as synchronized
always uses the object's monitor (intrinsic lock) as does code that synchronizes on the this
reference using a synchronized block. Poorly synchronized code is prone to contention and deadlock. An attacker can manipulate the system to trigger these conditions and cause a Denial of Service (DoS). If the vulnerable class is accessible from an untrusted class, an attacker can lock and hold the same object as the vulnerable class, disrupting correct synchronization.
Wiki Markup |
---|
The _private final lock object_ idiom prevents this vulnerability. The idiom consists of a {{java.lang.Object}} declared within the class as {{private}} and {{final}}. The object must be explicitly used for locking purposes in {{synchronized}} blocks, within the class's methods. This intrinsic lock is associated with the instance of the internal private object and not with the class itself. Consequently, there is no lock contention between this class's methods and methods of a hostile class \[[Bloch 01|AA. Java References#Bloch 01]\]. |
Static state has the same potential problem. If a static method is declared synchronized
, the intrinsic lock of the class object is acquired before executing the statements in its body, and released when the method completes. Any untrusted code that can access an object of the class, or a subclass, can use the getClass()
method to gain access to the class object. The private final lock object idiom can be used to protect static data by declaring the lock as private
, static
and final
. Reducing the accessibility of the class to package-private may offer some reprieve protection from untrusted callers when using strategies other than internal locking.
This idiom can also be suitably used by is also suitable for classes designed for inheritance. If a superclass thread requests a lock on the object's monitor, a subclass thread can interfere with its operation. For example, a subclass may use the superclass object's intrinsic lock for performing unrelated operations, causing significant lock contention. Also, excessive use of the same lock frequently results in deadlocks. This idiom separates the locking strategy of the superclass from that of the subclass. It also permits fine-grained locking because multiple lock objects can be used for seemingly unrelated operations. This increases the overall responsiveness of the application.
An object should use an internal private final lock object rather than its own intrinsic lock unless the class can guarantee that untrusted code cannot:
- subclass the class or its superclass (trusted code is allowed to subclass the class)
- create an object of the class (or , its superclass, or subclass)
- access or acquire an object instance of the class (or , its superclass, or subclass)
If a class uses an internal private lock to synchronize shared data, subclasses must also use an internal private lock. However, if a class uses intrinsic synchronization over the class object without documenting its locking policy, subclasses may not use intrinsic synchronization over their own class object, unless they explicitly document their locking policy. If the superclass documents its policy by stating that client-side locking is supported, the subclasses have the option of choosing between intrinsic locking over the class object and an internal private lock. Regardless of what is chosen, subclasses must document their locking policy. Refer to the guideline CON10-J. Do not override thread-safe methods with methods that are not thread-safe for related information.
...
This noncompliant code example exposes instances of the object someObject
class to untrusted code.
Code Block | ||
---|---|---|
| ||
public class SomeObject { public synchronized void changeValue() { // Locks on the object's monitor // ... } } // Untrusted code synchronized (someObject) { while (true) { Thread.sleep(Integer.MAX_VALUE); // Indefinitely delay someObject } } |
The untrusted code attempts to acquire a lock on the object's monitor and upon succeeding, introduces an indefinite delay which prevents the synchronized
changeValue()
method from acquiring the same lock. Note that the untrusted code also intentionally violates CON20-J. Do not perform operations that may block while holding a lock.
...
This noncompliant code example locks on a public
non-final object in an attempt to use a lock that differs from other than SomeObject
's own intrinsic lock.
Code Block | ||
---|---|---|
| ||
public class SomeObject { public Object lock = new Object(); public void changeValue() { synchronized (lock) { // ... } } } |
However, it is possible for untrusted code to change the value of the lock object and foil all attempts to synchronize on the correct objectdisrupt proper synchronization.
Noncompliant Code Example (publicly-accessible final lock object)
...