类加载的时机和初始化的时机
摘自:https://www.cnblogs.com/javaee6/p/3714716.html
类加载的时机:
-
Java核心类库(如rt.jar)
在虚拟机启动的时候进行预加载,各个类库被不同的ClassLoader所加载- Bootstrap ClassLoader/启动类加载器
主要负责jdk_home/lib目录下的核心 api 或 -Xbootclasspath 选项指定的jar包装入工作. - Extension ClassLoader/扩展类加载器
主要负责jdk_home/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar包装入工作
- Bootstrap ClassLoader/启动类加载器
-
用户自己定义的类
在虚拟机启动的时候被加载- System ClassLoader/系统类加载器
主要负责java -classpath/-Djava.class.path所指的目录下的类与jar包装入工作
体现了Java语言的动态性,在合适的时候被加载进JVM中 - User Custom ClassLoader/用户自定义类加载器(java.lang.ClassLoader的子类)
在程序运行期间, 通过java.lang.ClassLoader的子类动态加载class文件, 体现java动态实时类装入特性.
- System ClassLoader/系统类加载器
类初始化的时机:
1. 新建对象实例
2. 访问静态变量和静态方法时
3. 使用java.lang.reflect进行反射调用时
4. 初始化一个类时,其父类还没有进行初始化
5. 虚拟机启动时,定义main()方法的那个类先初始化
初始化类的执行顺序
摘自:https://www.cnblogs.com/Qian123/p/5713440.html
-
一般顺序
- 静态变量声明,静态代码块
- 普通变量声明,代码块
- 构造函数
-
包含继承
- 父类静态代码块,子类静态代码块
- 父类代码块,父类构造函数
- 子类代码块,子类构造函数
-
包含main()方法
- 包含main()方法的类的静态块
- main()方法
- 根据main()方法中的声明按需加载
只有涉及到实例对象才会去执行代码块和构造函数,否则初始化阶段只会执行静态变量赋值,静态代码块(即clinit()方法)