27
votes

I am looking at some disassembled code obtained from Java bytecode. I see some declaration as follows:

.method static synthetic access$0()Lcom/package/Sample;

I am not able to figure out what the synthetic or access$0 mean. Can someone please help me understand this part?

3
I can't believe it's not natural!user541686

3 Answers

28
votes

Synthetic field, (2)

A compiler-created field that links a local inner class to a block's local variable or reference type parameter.

See also The JavaTM Virtual Machine Specification (§4.7.6) or Synthetic Class in Java.

34
votes

In the java language, inner classes can access private members of their enclosing class. However, in Java bytecode, the concept of inner classes does not exist, and the private members are not accessible. To work around this, the compiler creates synthetic accessor methods in the outer class. I believe that is what you are seeing here. access$0 is simply the name of the method. I'm not sure what, if anything the synthetic does. It may just hide the method from other compilers to ensure encapsulation.

4
votes

assert statement JDK 1.8 case study

The assert statement is an example of construct that generates a static synthetic field in Oracle JDK 1.8.0_45:

public class Assert {
    public static void main(String[] args) {
        assert System.currentTimeMillis() == 0L;
    }
}

basically compiles to:

public class Assert {
    // This field is synthetic.
    static final boolean $assertionsDisabled =
        !Assert.class.desiredAssertionStatus();
    public static void main(String[] args) {
        if (!$assertionsDisabled) {
            if (System.currentTimeMillis() != 0L) {
                throw new AssertionError();
            }
        }
    }
} 

This can be verified with:

javac Assert.java
javap -c -constants -private -verbose Assert.class

which contains:

    static final boolean $assertionsDisabled;
  descriptor: Z
  flags: ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC

The synthetic field is generated so that Java only needs to call Assert.class.desiredAssertionStatus() once at load time, and it then caches the result there.

See also: https://stackoverflow.com/a/29439538/895245 for a more detailed explanation.

Note that this synthetic field can generate name conflicts with other fields we may define. E.g., the following fails to compile on Oracle JDK 1.8.0_45:

public class Assert {
    static final boolean $assertionsDisabled = false;
    public static void main(String[] args) {
        assert System.currentTimeMillis() == 0L;
    }
}

The only thing that "prevents" that is the naming convention of not using dollars on your identifiers. See also: When should I use the dollar symbol ($) in a variable name?

Bonus:

static final int $assertionsDisabled = 0;

would work, because unlike Java, the bytecode allows multiple fields with the same name but different types: Variables having same name but different type