Lambda表达式运行时生成类的性质及JVM解析相关疑问
关于Lambda表达式实例toString输出的技术问题解答
测试代码
public class Foo { // enclose class public static void main(String[] args) { System.out.println(new Foo().new InnerFoo()); IntSupplier intSupplier = () -> 42; System.out.println(intSupplier); } class InnerFoo{} // inner class }
执行输出
Foo$InnerFoo@3af49f1c Foo$$Lambda$15/0x0000000840064c40@13221655
问题解答
该实例不是内部类
- 常规内部类是编译期就生成独立的
.class文件(比如Foo$InnerFoo.class),而$$Lambda开头的实例是JVM在运行时动态生成的Lambda代理类实例,不属于用户定义的内部类范畴。 - 加载时长:这个动态生成的Lambda类会在首次执行Lambda表达式时被加载,加载后会常驻JVM的元空间(Metaspace),直到JVM进程终止才会被卸载,不会被垃圾回收机制主动回收。
- 常规内部类是编译期就生成独立的
$$Lambda标识的含义与JVM解析逻辑
$$Lambda是JVM为动态生成的Lambda代理类分配的专属命名标识,用来和用户定义的内部类(用单个$分隔命名)区分开;格式中的$15是该Lambda在当前类中的唯一序号,0x0000000840064c40是该代理类的内存地址或类的唯一标识后缀。- JVM解析流程:
- 首次执行Lambda表达式时,JVM通过
LambdaMetafactory工厂类动态生成一个实现目标函数式接口(此处为IntSupplier)的代理类; - 生成的代理类会以
$$Lambda为命名标识加载到元空间; - 创建代理类实例后,调用接口方法时会直接执行Lambda体中的代码(此处即返回42)。
- 首次执行Lambda表达式时,JVM通过
内容的提问来源于stack exchange,提问作者RBS
相关产品推荐
相关产品推荐

