|
The Java Specialists' Newsletter
Issue 192b 2011-06-01
Category:
Concurrency
Java version: Java 5.0-7.0 How Does "this" Escape?by Dr. Heinz M. KabutzAbstract: A quick follow-up to the previous newsletter, to show how the ThisEscape class is compiled, causing the "this" pointer to leak.
When I posted the previous
newsletter, I did not explicitly show how the
"this" reference escapes implicitly. I have been showing
these mysteries in my Java courses since 1999 and I forgot
that there might be some mortals who have never seen a
decompiled inner class ;-)
Our New Java Design Patterns Self-Study Course is Now Available
How Does "this" Escape?
When you construct a inner class within a non-static context,
such as in a non-static method, a constructor or an
initializer block, the class always has a pointer to
the outer object.
Here again is our class ThisEscape:
import java.util.*;
public class ThisEscape {
private final int num;
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
});
num = 42;
}
private void doSomething(Event e) {
if (num != 42) {
System.out.println("Race condition detected at " +
new Date());
}
}
}
When it gets compiled, javac generates two classes. The
outer class looks like this:
import java.util.*;
public class ThisEscape {
private final int num;
public ThisEscape(EventSource source) {
source.registerListener(new ThisEscape$1(this));
num = 42;
}
private void doSomething(Event e) {
if (num != 42)
System.out.println(
"Race condition detected at " + new Date());
}
static void access$000(ThisEscape _this, Event event) {
_this.doSomething(event);
}
}
Note how the compiler added the static, package access method
access$000(). Note also how it passed a pointer
to this into the constructor for the
anonymous inner class ThisEscape$1.
Next we have the anonymous inner class. It is package
access, with a package access constructor. Internally it
maintains a reference to the ThisEscape object. Note:
the anonymous class sets the this$0 field
before calling super(). This is the only
place where this is allowed in Java.
class ThisEscape$1 implements EventListener {
final ThisEscape this$0;
ThisEscape$1(ThisEscape thisescape) {
this$0 = thisescape;
super();
}
public void onEvent(Event e) {
ThisEscape.access$000(this$0, e);
}
}
Hopefully it is now clearer how the "this" pointer is
implicitely leaked.
Kind regards from Crete
Heinz
Concurrency Articles
Related Java Course
Discuss at The Java Specialist Club
|