...
- 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
thisusingpublic 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). Also see OBJ08-J. Avoid using finalizers. 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 "
this" reference of the internal object.
...
This noncompliant code example publishes the this reference before initialization has concluded, by storing it in a public static volatile class field. Consequently, other threads may obtain a partially initialized Publisher instance.
| Code Block | ||
|---|---|---|
| ||
class Publisher {
public static volatile Publisher pub; // Also noncompliant if field is nonvolatile
int num;
Publisher(int number) {
pub = this;
// Initialization
this.num = number;
// ...
}
}
|
Consequently, other threads may obtain a partially initialized Publisher instance. Also, if the object initialization (and consequently, its construction) depends on a security check within the constructor, the security check will be bypassed if an untrusted caller obtains the partially initialized instance (see OBJ04-J. Do not allow partially initialized objects to be accessed for more details).
...
| Code Block | ||
|---|---|---|
| ||
class Publisher {
public static Publisher pub;
int num;
Publisher(int number) {
// Initialization
this.num = number;
// ...
pub = this;
}
}
|
Because , the field is nonvolatile and nonfinal, the statements within the constructor can be reordered by the compiler in such a way that the this reference is published before the initialization statements have executed.
Compliant Solution (volatile field and publish after initialization)
This noncompliant code example declares the pub field as volatile and reduces the accessibility of the static class field to package-private so that untrusted callers beyond the current package cannot obtain the this reference.
...
The constructor publishes the this reference after initialization has concluded. However, the caller must 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 reference to Publisher may need to be declared volatile in the caller.
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.
...
This ensures that threads do not see a compromised Publisher instance. The num variable field is also declared as final; consequently, which makes the class is immutable; consequently . Consequently, there is no threat of a caller invoking newInstance() to obtain a partially initialized object.
...
| Code Block | ||
|---|---|---|
| ||
// Class DefaultExceptionReporter
public class DefaultExceptionReporter implements ExceptionReporter {
public DefaultExceptionReporter(ExceptionReporter er) {
// Carry out initialization
// Incorrectly publishes the "this" reference
er.setExceptionReporter(this);
}
// publicImplementation voidof reportsetExceptionReporter(Throwable exception) { /* default implementation */ }and report()
}
|
The class MyExceptionReporter subclasses DefaultExceptionReporter with the intent of adding a logging mechanism that logs critical messages before an exception is reported.
| 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);
}
}
|
...
If any 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 erroneous behavior results from the race condition between an oncoming exception and the initialization of MyExceptionReporter. If the exception comes too soon, it finds MyExceptionReporter in a compromised state. This behavior is especially counter intuitive because logger is declared final and is not expected to contain an unintialized value.
...
Instead of publishing the this reference from the DefaultExceptionReporter constructor, this compliant solution adds a uses the setExceptionReporter() method to DefaultExceptionReporter that can be called from a subclass, after its 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()
}
|
After constructing an object of class DefaultExceptionReporter, or a subclass thereof, you must explicitly call DefaultExceptionReporter.setExceptionReporter() The subclass MyExceptionReporter inherits the setExceptionReporter() method and a caller who instantiates MyExceptionReporter can use its instance to set the exception reporter, after initialization is over.
| 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");
}
}
|
This ensures that the reporter cannot be set before the constructor has fully initialized the subclass and logging has been enabled.
Noncompliant Code Example (inner class)
...
| Code Block | ||
|---|---|---|
| ||
public class DefaultExceptionReporter implements ExceptionReporter {
public DefaultExceptionReporter(ExceptionReporter er) {
er.setExceptionReporter(new DefaultExceptionReporter(er) {
public void report(Throwable t) {
filter(t);
}
});
}
// Default implementations of setExceptionReporter() and report()
}
|
The problem occurs because the this reference of the outer class is published by the inner class so that other threads can see it. If Furthermore, if the class is subclassed, the issue described in the previous noncompliant code example resurfaces.
...
| Wiki Markup |
|---|
A {{private}} constructor alongside a {{public static}} factory method can be used to safely publish the {{filter()}} method from within the constructor \[[Goetz 06|AA. Java References#Goetz 06]\]. |
...
Compliant Solution (thread)
In this This compliant solution , creates and starts the thread is created and started in a method , not in the constructor. Consequently, the this item is never passed to an alien method during instead of the constructor.
| Code Block | ||
|---|---|---|
| ||
class ThreadStarter implements Runnable {
public ThreadStarter() {
// ...
}
public void startThread() {
thread = new Thread(this);
thread.start();
}
public void run() {
// ...
}
}
|
Exceptions
| Wiki Markup |
|---|
*CON14-J:EX1*: It may be safe to invoke methods or constructors provided by the JRE that are known to handle the {{this}} object safely. In this code exampleexception, 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]\]. |
...