All 15 Inner Classes & Anonymous Classes questions
More in Inner Classes & Anonymous Classes
Advertisement
Back to results for “OOP”
Java › Inner Classes & Anonymous Classes

How does the compiler implement inner classes at the bytecode level, and what synthetic elements (like a hidden outer-class reference field and synthetic accessor methods) does it generate to make this work?

Advanced

Answer

The compiler translates a non-static inner class into a genuinely separate top-level class file (named OuterClass$InnerClass.class) at compile time, adding a synthetic (compiler-generated, not visible in source code) final field (conventionally named this$0) holding the implicit reference to the enclosing instance, automatically passed as an extra constructor argument whenever an inner class instance is created -- additionally, if the inner class accesses a PRIVATE member of the outer class (or vice versa), since bytecode-level access control doesn't have a native concept of 'nested class' the way source-level Java does, the compiler generates synthetic (package-private, bridge) accessor methods to bridge this access at the bytecode level, all entirely transparent to the source-level programmer but visible if you decompile the resulting bytecode.
// Source-level Java (what you write)
public class Outer {
    private int secret = 42;
    class Inner {
        void reveal() { System.out.println(secret); }  // accesses Outer's private field
    }
}

// Conceptually, the compiler generates something resembling:
// class Outer$Inner {
//     final Outer this$0;  // synthetic field holding the outer instance reference
//     Outer$Inner(Outer outer) { this.this$0 = outer; }
//     void reveal() { System.out.println(Outer.access$000(this$0)); }  // synthetic accessor for the private field
// }
Real-world example A developer decompiling a compiled inner-class-heavy codebase for debugging purposes is initially confused by unfamiliar synthetic method names like access$000 appearing in the decompiled output, until realizing these are compiler-generated bridge methods enabling private-field access across the inner/outer class boundary at the bytecode level, entirely invisible in the original source code.

Common follow-ups: Why does the JVM bytecode format not have a native concept of nested classes that source-level Java does?;What performance overhead, if any, do these synthetic accessor methods introduce compared to a direct field access?