Initialization-on-demand holder idiom:静态内部类加载初始化时机及JVM定义问题
关于初始化按需持有者模式的类加载与初始化问题解答
嘿,针对你深入研究Singleton时遇到的两个关于静态内部类的问题,我来一步步给你拆解清楚:
1. 静态内部类究竟何时被Loaded、何时被Initialised?
首先得明确JVM里**加载(Loading)和初始化(Initialisation)**是两个完全独立的阶段:
- 加载阶段:JVM只会在首次遇到对该静态内部类的主动引用时触发加载。在初始化按需持有者的场景里,就是当你调用外部类的
getInstance()方法,第一次访问到静态内部类的静态成员(比如那个Singleton实例)的时候,JVM才会去加载这个内部类的字节码,生成对应的Class对象存到方法区。 - 初始化阶段:加载完成后会紧接着触发初始化——这时候JVM会执行内部类的静态代码块,给静态变量赋值(也就是创建Singleton实例的核心过程)。而且这个初始化过程是JVM原生保证线程安全的,不会出现多线程下实例重复创建的问题。
这里要划个关键重点:外部类的加载和初始化绝对不会触发静态内部类的加载/初始化。比如你只是new了外部类的实例,或者访问外部类的静态成员,静态内部类依然会处于未加载状态,这也是这种Singleton模式能实现完美懒加载的核心原因。
2. 若该类未被加载,私有静态内部类在JVM中是如何被定义的?
当静态内部类还没被加载时,它并没有在JVM的方法区中生成可使用的Class对象。不过,外部类的Class对象里会包含这个内部类的基础元数据信息(比如类名、访问修饰符等),但这些信息只是以字节码结构的形式存在于外部类的class文件中,并没有被JVM解析成可调用的类结构。
另外,虽然这个内部类被标记为private,但JVM层面会通过合成一些桥接方法来允许外部类访问它的静态成员(比如那个Singleton实例),不过这都是加载之后的事了。在未加载状态下,这个内部类只是外部类字节码里的一个"定义模板",只有当触发了主动引用的条件,JVM才会把它加载进来,变成真正可使用的类实体。
内容的提问来源于stack exchange,提问作者pranavmalhotra
相关产品推荐
相关产品推荐

