Imagine a threaded model, where ThreadUtils.doFoo(FooBean fb)
would spawn a thread that would work with fb
. fb
could be as simple as parameters to be passed to that thread to define its computation. Now, take the following constructor:
public FooBean(int i, int j, int k, int l, int port){
ThreadUtils.doFoo(this);
someListField = Arrays.asList(i, j, k, l);
this.port = port;
}
This causes this
to leak out of the constructor. If for some spurious reason the spawned thread acted before the list was properly instantiated and assigned, you'd have a thread working on an inconsistent state of this
. If, for instance, port
was used by the new thread to listen on a socket, and this
got leaked, the socket may listen on port 0 (default value of a numeric field), and not on port port
.
In fact, an exception in the constructor can be an issue if this
is leaked and gets a reachable strong reference from elsewhere.
However, the following constructor is safe:
public FooBean(int i, int j, int k, int l, int port){
someListField = Arrays.asList(i, j, k, l);
this.port = port;
ThreadUtils.doFoo(this);
}
That is because in the Java memory model, the fields are stored before the thread even gets spawned.