Lambdas internalshard5-8 years

A teammate says `x -> x + 2` "desugars to an anonymous inner class, same as Java 7's anonymous `Runnable`." Someone else notices the stack trace shows a class named `Composition$$Lambda/0x00000...`, not `Composition$1`. What does a lambda actually compile to, and why does the naming difference matter beyond cosmetics?

A lambda does not compile to an anonymous inner class at all — there's no .class file for it sitting in the build output the way Composition$1.class would exist for an anonymous Runnable. Instead, the lambda's body becomes a small private method on the enclosing class, and the place in the code where the lambda was written becomes a single invokedynamic instruction. The first time that instruction actually executes, the JVM resolves it through a bootstrap mechanism, LambdaMetafactory, which generates a hidden implementation class at run time and caches it against that exact call site — every later execution of the same lambda expression reuses the cached class instead of generating it again. That's exactly why the stack trace shows a synthetic name like Composition$$Lambda/0x... rather than a compile-time nested-class name like Composition$1 — it genuinely was never compiled as a nested class, it was manufactured by the metafactory the first time that call site ran.

The lesson behind it →