if you overview the bytecode of a java class file, maybe you will find a keyword synthetic which is not include in the keyword of java language. so when will synthetic come out in the bytecode in a class file?
Any constructs introduced by the compiler that do not have a corresponding construct in the source code must be marked as synthetic, except for default constructors and the class initialization method.[1]
it means when there is a field or method introduced into a class file by the compiler and we can not find the primary declaration in the source file, it will marked as synthetic. let us have a look at a simple example.
public class A{
private int aSynthetic;
public int noSynthetic;
class B{
public void test(){
System.out.println(aSynthetic);
System.out.println(bSynthetic);
}
}
}
so let's see what the compiler output:
// Compiled from A.java (version 1.6 : 50.0, super bit)
public class A {
// Field descriptor #6 I
private int aSynthetic;
// Field descriptor #6 I
public int noSynthetic;
// Method descriptor #9 ()V
// Stack: 1, Locals: 1
public A();
0 aload_0 [this]
1 invokespecial java.lang.Object() [11]
4 return
Line numbers:
[pc: 0, line: 24]
Local variable table:
[pc: 0, pc: 5] local: this index: 0 type: A
// Method descriptor #18 (LA;)I
// Stack: 1, Locals: 1
static synthetic int access$0(A arg0);
0 aload_0
1 getfield A.aSynthetic : int [19]
4 ireturn
Line numbers:
[pc: 0, line: 25]
Inner classes:
[inner class info: #24 A$B, outer class info: #1 A
inner name: #26 B, accessflags: 0 default]
}
// Compiled from A.java (version 1.6 : 50.0, super bit)
class A$B {
// Field descriptor #6 LA;
final synthetic A this$0;
// Method descriptor #8 (LA;)V
// Stack: 2, Locals: 2
A$B(A arg0);
0 aload_0 [this]
1 aload_1
2 putfield A$B.this$0 : A [10]
5 aload_0 [this]
6 invokespecial java.lang.Object() [12]
9 return
Line numbers:
[pc: 0, line: 27]
Local variable table:
[pc: 0, pc: 10] local: this index: 0 type: A.B
// Method descriptor #14 ()V
// Stack: 2, Locals: 1
public void test();
0 getstatic java.lang.System.out : java.io.PrintStream [20]
3 aload_0 [this]
4 getfield A$B.this$0 : A [10]
7 invokestatic A.access$0(A) : int [26]
10 invokevirtual java.io.PrintStream.println(int) : void [32]
13 getstatic java.lang.System.out : java.io.PrintStream [20]
16 aload_0 [this]
17 getfield A$B.this$0 : A [10]
20 getfield A.noSynthetic : int [38]
23 invokevirtual java.io.PrintStream.println(int) : void [32]
26 return
Line numbers:
[pc: 0, line: 29]
[pc: 13, line: 30]
[pc: 26, line: 31]
Local variable table:
[pc: 0, pc: 27] local: this index: 0 type: A.B
Inner classes:
[inner class info: #1 A$B, outer class info: #27 A
inner name: #45 B, accessflags: 0 default]
}
so we can find a synthetic field A this$0 which is a reference to the outer class A. it is introduced by compiler so that you can use the field in the inner class without any troubles.
also we can find 7 invokestatic A.access$0(A) : int [26] in the class B when we visit aSynthetic field but no such bytecode when we visit noSynthetic.
The reason is aSynthetic is a private field which can not be accessed outside the class A, so the compiler supply a access$0 method to visit the private field in the outer class. the 0 is a index to the field array. as the same we don't need to use such method when we access a outer class' public or protect field.
[1] The Java Language Specification 3rd