类加载过程学习笔记

1.加载(重要)
加载阶段是“类加载机制”中的一个阶段,这个阶段通常也被称作“装载”,主要完成:
1.1.通过“类全名”来获取定义此类的二进制字节流
1.2 将字节流所代表的静态存储结构转换为方法区的运行时数据结构
1.3 在java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据的访问入口
相对于类加载过程的其他阶段,加载阶段(准确地说,是加载阶段中获取类的二进制字节流的动作)是开发期可控性最强的阶段,因为加载阶段可以使用系统提供的类加载器(ClassLoader)来完成,也可以由用户自定义的类加载器完成,开发人员可以通过定义自己的类加载器去控制字节流的获取方式。
加载阶段完成后,虚拟机外部的二进制字节流就按照虚拟机所需的格式存储在方法区之中,方法区中的数据存储格式有虚拟机实现自行定义,虚拟机并未规定此区域的具体数据结构。然后在java堆中实例化一个java.lang.Class类的对象,这个对象作为程序访问方法区中的这些类型数据的外部接口。

2.链接(验证,准备,解析)
2.1.验证:验证class文件的格式,语法,java字节码及操作数的正确性,还有兼容性等问题
2.2.准备: 给静态变量 分配空间 ,并设定一个默认值
2.3.解析: 将类中的符号引用(变量名)转换成 直接引用 (指针,指向方法在方法区中具体的内存地址)

4.初始化:为静态变量赋上正确的初始值,在类的首次主动调用时都会初始化
什么是主动调用呢?
4.1   new一个类实例
4.2 访问一个类方法和类属性(非final常量),或通过get,Set方法获取/设置类的非常量属性(注意:直接通过 类名.【静态常量】属性 的方式不会初始化类,常量在编译期间优化为直接引用??)
4.3用java的反射机制Class.forname()也会初始化类
4.4 初始化一个类的子类对象,会先初始化父类
  (注:1. 接口除外,父接口在调用的时候才会被初始化;
            2.子类引用父类静态字段,只会引发父类初始化)
4.5 java虚拟机启动时被标记启动的类
疑问:序列化反序列化会调用吗?
1)一个类没父类时,不会初始化
2)如果一个类有父类
      2.1)父类没有实现序列化接口,那么在反序列化时父类会初始化(测试是初始化非静态代码块,可能是因为JVM中已经有静态)
      2.2)父类也实现序列化接口,那么在反序列化时父类不会初始化

类加载顺序
类加载的顺序如果是一个类的话,加载的顺序是:

1)类的静态属性

2)类的静态代码块

3)类的非静态属性

4)类的非静态代码块

5)构造方法

如果一个类有父类,加载的顺序是:

父类的静态属性

父类的静态代码块

子类的静态属性

子类的静态代码块

父类的非静态属性

父类的非静态代码块

父类的构造方法

子类的非静态属性

子类的非静态代码块

子类的构造方法。

总结:先静态属性和代码块,接着是非静态属性和代码块,最后才是构造方法, 在此基础上 先父类再子类

1)静态>非静态>构造方法
2)成员属性>代码块
3)父类>子类





猜你喜欢

转载自blog.csdn.net/hh1sdfsf56456/article/details/80534718