解析Java虚拟机中类的初始化及加载器的父委托机制
1. 类的加载过程
- 类的加载过程包含:加载、连接和初始化三个步骤。
- 加载过程:通过获取字节流,将.class文件放入内存,并产生一个代表该类的Class对象。
- 连接过程:分为验证、准备、解析三个阶段,其中解析阶段可能会涉及到类或接口的初始化。
- 初始化过程:为类的静态变量赋予正确的初始值,进行类构造器
()方法的调用。
2. 类的初始化
- 当Java程序对某个类进行初始化时,如下操作可能会触发类的初始化:
- 当程序创建某个类的新实例时、
- 当访问该类的静态变量时、
- 当调用该类的静态方法时、
-
当Java虚拟机启动某个类时(如程序的入口方法main())。
-
类初始化的步骤如下:
- 确认类已经被加载、连接后;
- 执行类的
()方法——类的构造器方法,为类的静态变量赋值并执行静态块。
3. 加载器的父委托机制
- 加载器的父委托机制是ClassLoader的读代码时常说的重要特性之一。
- 当我们需要加载某个类时,先从最近的加载器开始,依次向上委托它的父加载器进行加载。
- 如果父加载器未能找到该类,那么将会由其子加载器来进行加载。
4. 详细示例
- 示例1
```
class Person{
static final String WELCOME= "welcome";
static { System.out.println("Initialize for Person"); }
}
class InitDemo{
public static void main(String[] args){
System.out.println(Person.WELCOME);//使用类的静态变量
}
}
```
解析:
当外部程序访问Person.WELCOME变量时,如果类还未初始化,那么此时会先初始化Person类。在Person类初始化过程中,静态块中的代码先被执行,最终输出"Initialize for Person"。当Person类初始化完成后,再输出"WELCOME"。
- 示例2
```
class A{
static {System.out.println("Initialize for A");}
public static void f1(){}
}
class B{
static {System.out.println("Initialize for B");}
}
public class C{
static {
System.out.println("Initialize for C");
}
public static void main(String[] args){
A.f1();
}
}
```
解析:
当程序运行时,需要加载并执行main()方法,而main()方法中会调用class A的静态方法f1()。根据初始化的条件,程序会先初始化class A,调用静态块输出"Initialize for A"。在A类初始化完成之后,才会进入C类的主方法中,调用静态方法f1()。类B则因为无法访问,未进行初始化。因此输出结果为"Initialize for A"。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:解析Java虚拟机中类的初始化及加载器的父委托机制 - Python技术站