...
Because the the Helper
class is declared as public, it uses a private lock to handle synchronization in conformance with CON04-J. Use private final lock objects to synchronize classes that may interact with untrusted code.
Exceptions
*CON26-EX1:* Security sensitive objects prior to Java SE 6 (but under the revised Java Memory Model under JSR-133 (JMM) \[[JSR-133 04|AA. Java References#JSR-133 04]\]) checked a {{volatile}} {{boolean}} flag in every method of the class to ensure that the object is unusable when it is in an uninitialized or partially-initialized state. The flag was always set in the last statement of the initializing code. This guideline may be violated if the code uses this technique for providing backward compatibility or if the caller is untrusted and consequently, may not declare the object reference as volatile. Wiki Markup
This exception uses a volatile initialized flag. The corresponding Foo
class is the same as the noncompliant code example.
Code Block | ||
---|---|---|
| ||
public class Helper {
private int n;
private volatile boolean initialized; // Defaults to false
public Helper(int n) {
this.n = n;
this.initialized = true;
}
public void doSomething() {
if (!initialized) {
throw new SecurityException("Cannot use partially initialized instance");
}
// ...
}
// ...
}
|
This ensures that even if the reference to the Helper
object instance is published before its initialization is over, the instance is unusable. The instance is unusable because every method within Helper
must check the flag to determine whether the initialization has finished.
Classes that prevent partially initialized objects from being used may publish partially initialized objects. This may be implemented, for example, by setting a volatile
boolean
flag in the last statement of the initializing code and then ensuring this flag was set before allowing the execution of any class methods.
The following compliant solution illustrates this technique:
Code Block | ||
---|---|---|
| ||
public class Helper {
private int n;
private volatile boolean initialized; // Defaults to false
public Helper(int n) {
this.n = n;
this.initialized = true;
}
public void doSomething() {
if (!initialized) {
throw new SecurityException("Cannot use partially initialized instance");
}
// ...
}
// ...
}
|
This ensures that even if the reference to the Helper
object instance is published before its initialization is over, the instance is unusable. The instance is unusable because every method within Helper
must check the flag to determine whether the initialization has finished. From SE 6 onwards, this technique is superseded by a mechanism that recommends performing any checks that might leave the code uninitialized as a result of exceptions, in a call to a private constructor or a superclass constructor. An exception thrown before the completion of {{Object}}'s constructor ensures that a subclass cannot obtain a partially initialized instance \[[SCG 09|AA. Java References#SCG 09]\]. (For more information, see the guideline [OBJ04-J. Do not allow partially initialized objects to be accessed]) Wiki Markup
Risk Assessment
Failing to synchronize access to shared mutable data can cause different threads to observe different states of the object or a partially initialized object.
...