一. 类加载器在Java体系中的位置
二. 类的生命周期
三. 类加载过程----加载
- 加载过程的几个要素
类加载器:
主要操纵者.class文件:
被操纵者方法区:
操作区域一个java.lang.Class对象:
主要产物
- 类加载过程中的加载环节干了什么?
- 类加载器根据类的全限定名, 获取.class文件中的二进制字节流
- 将这个字节流代表的静态存储结构, 转换为方法区的运行时数据结构
- 在方法区中为这个类生成一个java.lang.Class对象, 作为方法区中这个类的访问入口
- 一个类在什么时候会被加载?
jvm规范并没有明确规定类加载的时机.
- 如何查看一个类是否被加载了?
添加jvm参数:
-XX:+TraceClassLoading
四. 类加载过程----连接
- 连接可以细化为三个步骤
验证:
文件格式验证, 元数据验证, 字节码验证, 符号引用验证准备:
为类变量分配内存并设置初始值(如int类型初始值为0, 引用类型初始值为null)解析:
虚拟机将常量池中的符号引用转化为直接引用的过程
五. 类加载过程----初始化
- 类的初始化做了什么
- 直接声明类变量
指定初始值
- 在静态代码块中为类变量
指定初始值
- 类的初始化逻辑
- 假如这个类还没有被加载和连接,则程序先加载并连接该类
- 假如该类的直接父类还没有被初始化,则先初始化其直接父类
- 假如类中有初始化语句,则系统
依次执行
这些初始化语句
- 一个类在什么时候会被初始化?
当一个类被
首次主动使用
时, 就会被初始化
一个类只能被初始化一次
- 什么情况下一个类会被主动使用?
- 实例化一个类时
- 访问一个类或接口的静态变量或为静态变量赋值
- 调用类的静态方法
- 反射(如 Class.forName(“com.test.Test”))
- 初始化某个类的子类,则其父类也会被初始化
- Java虚拟机启动时被标明为启动类的类
- 初始化阶段和准备阶段的比较
- 准备阶段是给类变量开辟内存空间, 并赋初值, 这个初值是jvm规定的
- 初始化阶段是给类变量指定初始值, 这个值是代码中显式指定的
六. 案例分析
public class Test3 {
public static void main(String[] args) {
System.out.println(Parent3.a);
System.out.println(Parent3.b);
System.out.println(Parent3.c);
}
}
class Parent3 {
static int a;
static int b = 0;
private static Parent3 parent3 = new Parent3();
private Parent3(){
a++;
b++;
c++;
}
static int c = 0;
}
打印结果为:
1
1
0
分析:
- 准备阶段: abc都为0
- 初始化阶段: 当构造方法被执行时后, abc都为1, 然后继续执行初始化语句, c又被赋值为0