这个主题主要是有两个方面,一个是类加载的过程,还有一个就是类加载器
首先来看类加载的过程
•加载:查找并加载类的二进制数据
•连接
–验证:确保被加载的类的正确性
–准备:为类的静态变量分配内存,并将其初始化为默认值,注意,这里所说的都是静态变量
–解析:把类中的符号引用转换为直接引用
•初始化:为类的静态变量赋予正确的初始值
类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构
•加载.class文件的方式
–从本地系统中直接加载
–通过网络下载.class文件
–从zip,jar等归档文件中加载.class文件,如我们在eclipse中使用JDK中的jar中提取。
–从专有数据库中提取.class文件
–将Java源文件动态编译为.class文件
•类的加载的最终产品是位于堆区中的Class对象
•Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口
•类加载器并不需要等到某个类被“首次主动使用”时再加载它
连接阶段:
验证:
类的准备:
准备阶段这里是静态变量,此时还没有关系到对象呢,还没有new呢,还没有任何一个对象生成。
pvivate static int a=3;在连接阶段,那么a=0,后面初始化时a的值才变为3的。实际上这个过程可以分解为private static int a;static{a=3}
类的解析:
开发的时候用1.6编译,但是你放到服务器时用的是1.5,那就有可能出现LinkageError错误
java中没有指针是对使用上来说的,实际上还是有的,在底层。
类的初始化:
静态变量的声明语句,静态代码块都被看作是类的初始化语句
类的初始化步骤:
1),假如这个类还没有被加载和连接,那就先进行加载和连接
2)假如这个类存在直接的父类,而且父类还没有被初始化,那就先初始化直接的父类
3)假如类中存在初始化语句,那就按顺序执行这些初始化语句
类的主动使用会导致类的初始化,被动使用不会导致类的初始化,什么是是主动使用呢
•主动使用(六种)
–创建类的实例 new Test()对Test这个类的主动使用
–访问某个类或接口的静态变量,或者对该静态变量赋值 int b=Test.a;或者Test.a=b
–调用类的静态方法 Test.doSomething();
–反射(如Class.forName(“com.shengsiyuan.Test”))
–初始化一个类的子类 class parent{} class Child extends parent{public static int a=3} main{Child.a=3}
–Java虚拟机启动时被标明为启动类的类(Java Test) java cn.wenping.Test 这也是叫对这个类的主动使用
类的初始化时机:
只有当程序访问的静态变量或静态方法确实在当前类或当前接口中定义时,才可以认为是对类或接口的主动使用
•调用ClassLoader类的loadClass方法加载一个类,并不是对类的主动使用,不会导致类的初始化。
x=6/3,x是个编译时的常量,当使用它时不会导致类的初始化!x=new Math.random(),即是要运行时才能确定的,所以会导致类的初始化。