When used as a primary expression, the keyword
thisdenotes a value that is a reference to the object for which the instance method was invoked (§15.12), or to the object being constructed....
The type of
thisis the class or interface type T within which the keyword
At run time, the class of the actual object referred to may be T, if T is a class type, or a class that is a subtype of T.
this reference is said to have escaped when it is made available beyond its current scope. Following are common ways by which the
this reference can escape:
thisfrom a nonprivate, overridable method that is invoked from the constructor of a class whose object is being constructed (for more information, see MET05-J. Ensure that constructors do not call overridable methods).
thisfrom a nonprivate method of a mutable class, which allows the caller to manipulate the object's state indirectly. This situation commonly occurs in method-chaining implementations (see VNA04-J. Ensure that calls to chained methods are atomic for more information).
thisas an argument to an alien method invoked from the constructor of a class whose object is being constructed.
- Using inner classes. An inner class implicitly holds a reference to the instance of its outer class unless the inner class is declared static.
- Publishing by assigning
thisto a public static variable from the constructor of a class whose object is being constructed.
- Throwing an exception from a constructor. Doing so may cause code to be vulnerable to a finalizer attack (see OBJ11-J. Be wary of letting constructors throw exceptions for more information).
- Passing internal object state to an alien method, which enables the method to retrieve the
thisreference of the internal member object.
This rule describes the potential consequences of allowing the
this reference to escape during object construction, including race conditions and improper initialization. For example, declaring a field final ordinarily ensures that all threads see the field in a fully initialized state; however, allowing the
this reference to escape during object construction can expose the field to other threads in an uninitialized or partially initialized state. TSM03-J. Do not publish partially initialized objects, which describes the guarantees provided by various mechanisms for safe publication, relies on conformance to this rule. Consequently, programs must not allow the
this reference to escape during object construction.
In general, it is important to detect cases in which the
this reference can leak out beyond the scope of the current context. In particular, public variables and methods should be carefully scrutinized.
Noncompliant Code Example (Publish before Initialization)
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 can obtain a partially initialized
If an object's initialization (and consequently, its construction) depends on a security check within the constructor, the security check can be bypassed when an untrusted caller obtains the partially initialized instance (see OBJ11-J. Be wary of letting constructors throw exceptions for more information).
Noncompliant Code Example (Nonvolatile Public Static Field)
This noncompliant code example publishes the
this reference in the last statement of the constructor. It remains vulnerable because the
published field has public accessibility and the programmer has failed to declare it as volatile.
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 compliant solution both declares the
published field volatile and reduces its accessibility to package-private so that callers outside the current package scope cannot obtain the
The constructor publishes the
this reference after initialization has concluded. However, the caller that instantiates
Publisher must ensure that it cannot see the default value of the
num field before it is initialized; to do otherwise would violate TSM03-J. Do not publish partially initialized objects. Consequently, the field that holds the reference to
Publisher might need to be declared volatile in the caller.
Initialization statements may be reordered when the
published field is not declared volatile. The Java compiler, however, forbids declaring fields as both volatile and final.
Publisher must also be final; otherwise, a subclass can call its constructor and publish the
this reference before the subclass's initialization has concluded.
Compliant Solution (Public Static Factory Method)
This compliant solution eliminates the internal member field and provides a
newInstance() factory method that creates and returns a
This approach ensures that threads cannot see an inconsistent
Publisher instance. The
num field is also declared final, making the class immutable and consequently eliminating the possibility of obtaining a partially initialized object.
Noncompliant Code Example (Handlers)
This noncompliant code example defines the
This interface is implemented by the
DefaultExceptionReporter class, which reports exceptions after filtering out any sensitive information (see ERR00-J. Do not suppress or ignore checked exceptions for more information).
DefaultExceptionReporter constructor prematurely publishes the
this reference before construction of the object has concluded. This occurs in the last statement of the constructor (
er.setExceptionReporter(this)), which sets the exception reporter. Because it is the last statement of the constructor, this may be misconstrued as benign.
MyExceptionReporter class subclasses
DefaultExceptionReporter with the intent of adding a logging mechanism that logs critical messages before reporting an exception.
MyExceptionReporter constructor invokes the
DefaultExceptionReporter superclass'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 to receive and handle exceptions from that point on.
Logging will fail when an exception occurs before the call to
Logger.getLogger() in the
MyExceptionReporter subclass because dereferencing the uninitialized
logger field generates a
NullPointerException, which could 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 arrives too soon, it will find the
MyExceptionReporter object in an inconsistent state. This behavior is especially counterintuitive because
logger has been declared final, so observing an uninitialized value would be unexpected.
Premature publication of an event listener causes a similar problem; the listener can receive event notifications before the subclass's initialization has finished.
Rather than publishing the
this reference from the
DefaultExceptionReporter constructor, this compliant solution adds a
publishExceptionReporter() method to
DefaultExceptionReporter to permit setting the exception reporter. This method can be invoked on a subclass instance after the subclass's initialization has concluded.
MyExceptionReporter subclass inherits the
publishExceptionReporter() method. Callers that instantiate
MyExceptionReporter can use the resulting instance to set the exception reporter after initialization is complete.
This approach ensures that the reporter cannot be set before the constructor has fully initialized the subclass and enabled logging.
Noncompliant Code Example (Inner Class)
Inner classes maintain a copy of the
this reference of the outer object. Consequently, the
this reference could leak outside the scope [Goetz 2002]. This noncompliant code example uses a different implementation of the
DefaultExceptionReporter class. The constructor uses an anonymous inner class to publish an exception reporter.
Other threads can see the
this reference of the outer class because it is published by the inner class. Furthermore, the issue described in the noncompliant code example for handlers will resurface if the class is subclassed.
Use a private constructor and a public static factory method to safely publish the exception reporter from within the constructor [Goetz 2006a]:
Because the constructor is private, untrusted code cannot create instances of the class; consequently, the
this reference cannot escape. Using a public static factory method to create new instances also protects against untrusted manipulation of internal object state and publication of partially initialized objects (see TSM03-J. Do not publish partially initialized objects for additional information).
Noncompliant Code Example (Thread)
This noncompliant code example starts a thread inside the constructor:
Compliant Solution (Thread)
This compliant solution creates and starts the thread in a method rather than in the constructor:
TSM01-J-EX0: It is safe to create a thread in the constructor, provided the thread is not started until after object construction is complete, because a call to
start() on a thread happens-before any actions in the started thread [JLS 2015].
Even though this code example creates a thread that references
this in the constructor, the thread is started only when its
start() method is called from the
startThread() method [Goetz 2002], [Goetz 2006a].
TSM01-J-EX1: Use of the
ObjectPreserver pattern [Grand 2002] described in TSM02-J. Do not use background threads during class initialization is safe and is permitted.
this reference to escape can result in improper initialization and runtime exceptions.
Section 3.2, "Publication and Escape"
Chapter 5, "Creational Patterns, Singleton"
|[JLS 2015]||§15.8.3, "|