...
- Returning
thisfrom a nonprivate (possiblyfinal) method invoked from the constructor of an object under construction - Passing
thisas an argument to an alien method invoked from the constructor of an object under construction. - Publishing by assigning
thisusing topublic staticvariables from the constructor of an object under construction - Calling a non-final method from a constructor (MET04-J. Ensure that constructors do not call overridable methods)
- Overriding the finalizer of a non-final class and obtaining the
thisreference of a partially initialized instance, when the construction of the object ceases (OBJ04-J. Do not allow partially initialized objects to be accessed). This usually happens when the constructor throws exceptions. Trusted code may also add a finalizer and letthisescape by violating OBJ08-J. Avoid using finalizers. - Passing internal object state to an alien method. This enables the method to retrieve the
thisreference of the internal object.
This guideline focuses on the potential consequences of this escaping during object construction including race conditions and improper initialization. For example, declaring a field final ensures that all threads will see it in a fully initialized state only when the this reference does not escape during the corresponding object's construction. The guideline CON26-J. Do not publish partially initialized objects discusses the guarantees provided by various mechanisms for safe publication and relies on conformance to this guideline. In general, it is important to detect cases where the this reference can leak out beyond the scope of the current context. In particular, public variables and methods should be carefully scrutinized.
...
This noncompliant code example publishes the this reference before initialization has concluded, by storing it in a public static volatile class field.
| Code Block | ||
|---|---|---|
| ||
final class Publisher { public static volatile Publisher pub; // Also noncompliant if field is nonvolatilenon-volatile int num; Publisher(int number) { pub = this; // Initialization this.num = number; // ... } } |
...
This noncompliant code example publishes the this reference in the last statement of the constructor but is still vulnerable because the field pub is not declared volatile and has public accessibility.
| Code Block | ||
|---|---|---|
| ||
final class Publisher {
public static Publisher pub;
int num;
Publisher(int number) {
// Initialization
this.num = number;
// ...
pub = this;
}
}
|
...
Compliant Solution (volatile field and publish after initialization)
This noncompliant code example compliant solution declares the pub field as volatile and reduces the its accessibility of the static class field to package-private so that untrusted callers existing beyond the current package cannot obtain the this reference.
...
The constructor publishes the this reference after initialization has concluded. However, the caller which instantiates Publisher, must ensure that it does not see the default value of the num field, before it is initialized (a violation of CON26-J. Do not publish partially initialized objects). Consequently, the field that holds the reference to Publisher may need to be declared volatile in the a caller that instantiates Publisher.
If Initialization statements may be reordered if the pub field is not declared as volatile initialization statements may be reordered. The Java compiler does not allow declaring the static pub field as final in this case.
The class Publisher should also be final, otherwise a subclass might execute call its constructor and consequently, publish the this reference before the subclass's initialization has concluded.
...
This compliant solution removes the internal field and provides a newInstance() factory method which that can be used to obtain an instance of the Publisher object.
| Code Block | ||
|---|---|---|
| ||
final class Publisher { final int num; private Publisher(int number) { // Initialization this.num = number; } public static Publisher newInstance(int number) { Publisher pupub = new Publisher(number); return pupub; } } |
This ensures that threads do not see a compromised Publisher instance. The num field is also declared as final, which makes the class immutable. Consequently, there is no threat of a caller invoking newInstance() to obtain a partially initialized object.
...
| Code Block | ||
|---|---|---|
| ||
// Class MyExceptionReporter derives from DefaultExceptionReporter
public class MyExceptionReporter extends DefaultExceptionReporter {
private final Logger logger;
public MyExceptionReporter(ExceptionReporter er) {
super(er); // Calls superclass's constructor
logger = Logger.getLogger("com.organization.Log"); // Obtain the default logger
}
public void report(Throwable t) {
logger.log(Level.FINEST,"Loggable exception occurred", t);
}
}
|
Its constructor invokes the superclass DefaultExceptionReporter's constructor (a mandatory first step) which publishes the exception reporter before the initialization of the subclass has concluded. Note that the subclass initialization consists of obtaining an instance of the default logger. Publishing the exception reporter is equivalent to setting it so that it can receive and handle exceptions from that point onwards.
If any an exception occurs before the call to Logger.getLogger() in the subclass MyExceptionReporter, it is not logged. Instead, a NullPointerException is generated which may itself be consumed by the reporting mechanism, without being logged.
...
This issue can also occur when an event listener is prematurely published. Consequently, it will start starts receiving event notifications even before the subclass's initialization has concluded.
...
Instead of publishing the this reference from the DefaultExceptionReporter constructor, this compliant solution uses the setExceptionReporter() method of DefaultExceptionReporter to set the exception reporter. This method can be invoked on a subclass instance, after the subclass's initialization has concluded.
| Code Block | ||
|---|---|---|
| ||
// Class DefaultExceptionReporter public class DefaultExceptionReporter implements ExceptionReporter { public DefaultExceptionReporter(ExceptionReporter er) { // ... } // Should be called after subclass's initialization is over public final void setExceptionReporter() { setExceptionReporter(this); // Registers this exception reporter } // Implementation of report() } |
...
| Code Block | ||
|---|---|---|
| ||
// Class MyExceptionReporter derives from DefaultExceptionReporter
public class MyExceptionReporter extends DefaultExceptionReporter {
private final Logger logger;
public MyExceptionReporter(ExceptionReporter er) {
super(er); // Calls superclass's constructor
logger = Logger.getLogger("com.organization.Log");
}
// Implementations of setExceptionReporter() and report() are inherited
}
|
This ensures that the reporter cannot be set before the constructor has fully initialized the subclass and logging has been enabled.
...
This noncompliant code example starts a thread from within the constructor.
| Code Block | ||
|---|---|---|
| ||
final class ThreadStarter implements Runnable {
public ThreadStarter() {
Thread thread = new Thread(this);
thread.start();
}
public void run() {
// ...
}
}
|
...
This compliant solution creates and starts the thread in a method instead of the constructor.
| Code Block | ||
|---|---|---|
| ||
final class ThreadStarter implements Runnable {
public ThreadStarter() {
// ...
}
public void startThread() {
Thread thread = new Thread(this);
thread.start();
}
public void run() {
// ...
}
}
|
...
| Wiki Markup |
|---|
*CON14:EX1*: In this exception, even though a thread referencing {{this}} is created in the constructor, it is not started until its {{start()}} method is called from method {{startThread()}} \[[Goetz 02|AA. Java References#Goetz 02]\], \[[Goetz 06|AA. Java References#Goetz 06]\]. |
| Code Block | ||
|---|---|---|
| ||
final class ThreadStarter implements Runnable {
Thread thread;
public ThreadStarter() {
thread = new Thread(this);
}
public void startThread() {
thread.start();
}
public void run() {
// ...
}
}
|
...