Step1: I compiled the following code:
public class OuterClass {
class InnerClass{
}
}
I've got OuterClass.class and OterClass$InnerClass.class
Step2: I use javap to check the bytecode of the inner class. It is very strange that the constructor method uses " 1: aload_1", but in the LocalVariableTable, there is only one entry for "this" that is accessible by aload_0. I assume that aload_1 is to load the passing-in parameter--which is the reference of the outer class object--to the top of the stack.
My Question : Why doesn't the compiler create an entry for it(the reference of the outer class that is passed to the constructor)?
I tried with Jsdk 1.4 and openjdk 1.6.
~$ javap -v -c OuterClass\$InnerClass
Compiled from "OuterClass.java"
class OuterClass$InnerClass extends java.lang.Object
SourceFile: "OuterClass.java"
InnerClass:
#24= #1 of #22; //InnerClass=class OuterClass$InnerClass of class OuterClass
minor version: 0
major version: 50
Constant pool:
const #1 = class #2; // OuterClass$InnerClass
const #2 = Asciz OuterClass$InnerClass;
const #3 = class #4; // java/lang/Object
const #4 = Asciz java/lang/Object;
const #5 = Asciz this$0;
const #6 = Asciz LOuterClass;;
const #7 = Asciz <init>;
const #8 = Asciz (LOuterClass;)V;
const #9 = Asciz Code;
const #10 = Field #1.#11; // OuterClass$InnerClass.this$0:LOuterClass;
const #11 = NameAndType #5:#6;// this$0:LOuterClass;
const #12 = Method #3.#13; // java/lang/Object."<init>":()V
const #13 = NameAndType #7:#14;// "<init>":()V
const #14 = Asciz ()V;
const #15 = Asciz LineNumberTable;
const #16 = Asciz LocalVariableTable;
const #17 = Asciz this;
const #18 = Asciz LOuterClass$InnerClass;;
const #19 = Asciz SourceFile;
const #20 = Asciz OuterClass.java;
const #21 = Asciz InnerClasses;
const #22 = class #23; // OuterClass
const #23 = Asciz OuterClass;
const #24 = Asciz InnerClass;
{
final OuterClass this$0;
OuterClass$InnerClass(OuterClass);
Code:
Stack=2, Locals=2, Args_size=2
0: aload_0
1: aload_1
2: putfield #10; //Field this$0:LOuterClass;
5: aload_0
6: invokespecial #12; //Method java/lang/Object."<init>":()V
9: return
LineNumberTable:
line 3: 0
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 this LOuterClass$InnerClass;
}
The LocalVariableTable
is purely for debugging purposes - it has no effect on execution. Therefore, it only includes the source visible variables, since that's what the debugger is interested in. There's no reason to include compiler generated variables.
I think it's just because it doesn't need an entry in the local variable table, being an argument that never needs to get referenced in any other way than as an argument.