Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: few more edits

...

...

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
bgColor#FFcccc
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
bgColor#FFcccc
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
bgColor#FFcccc
// 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
bgColor#FFcccc
// 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
bgColor#ccccff
// 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
bgColor#ccccff
// 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
bgColor#FFcccc
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
bgColor#ccccff
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]\].

...