You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

Noncompliant Code Example (getClass() lock object)

Synchronizing on return values of the Object.getClass() method, rather than a class literal can lead to unexpected behavior. Whenever the implementing class is subclassed, the subclass locks on a completely different Class object (subclass's type).

public void doSomething() {
  synchronized(getClass()) {
    // ... 
  }
}

Section 4.3.2 "The Class Object" of the Java Language specification [[JLS 05]] describes how method synchronization works:

A class method that is declared synchronized synchronizes on the lock associated with the Class object of the class.

This does not mean that a subclass using getClass() can only synchronize on the Class object of the base class. In fact, it will lock on its own Class object, which may or may not be what the programmer had in mind. The intent should be clearly documented or annotated.

Compliant Solution (class name qualification)

Explicitly define the name of the class through name qualification (superclass in this compliant solution) in the synchronized block.

public void doSomething() {
  synchronized(SuperclassName.class) { 
    // ... 
  }
}

The class object that is being used for synchronization should not be accessible to untrusted code. If the class is package-private, callers from other packages may not access the class object, ensuring its trustworthiness as an intrinsic lock object. For more information, see CON04-J. Synchronize using an internal private final lock object.

Compliant Solution (Class.forName())

This compliant solution uses the Class.forName() method to synchronize on the superclass's Class object.

public void doSomething() {
  synchronized(Class.forName("SuperclassName")) { 
    // ... 
  }
}

The class object that is being used for synchronization should also not be accessible to untrusted code. Furthermore, care must be taken to ensure that untrusted inputs are not accepted as arguments while loading classes using Class.forname(). (See SEC05-J. Do not expose standard APIs that use the immediate caller's class loader instance to untrusted code for more information.)

  • No labels