第7章 虚拟机类加载机制
类的加载的时机
加载 Loading, 连接 Linking(验证 Verfiication, 准备Preparation, 解析 Resolution) 初始化 Initialization, 使用Using和卸载 Unloading
类加载的过程:
1,加载:
加载是“类加载" class loading过程珠一个阶段,在加载阶段,虚拟机需要完成以下3个事情。
1 通过一个类的全限定名来获取定义此类的二进制字节流
2 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
2、验证
1 文件格式验证:验证字节流是否符事Class文件格式的规范,并且能被当前版本的虚拟机处理。
2元数据验证:对字节码描述的信息进行语义分析。 这个类是否有父类,是否继承了不允许被继承的类。。。。
3 字节码验证:主要目的是通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。在第二阶段对元数据信息中的数据类型做完校验后,这个阶段将对类的方法体进行校验分析,保证被校验类的方法在运行时不会做出危害虚拟机安全的事件。保证任意时刻操作数栈的数据类型与指令代码序列都能配合工作,例如不会出现类似这样的情况,在操作栈放置了一个int类型的数据,使用时却按long类型来加载入本地变量表中。
4 符号引用验证 最后一阶段的校验发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在连接的第三阶段--解析阶段中发生。符号引用验证可以看做是对类自身以外的信息进行匹配性校验。 符号引用中通过字条串描述的全限定名是否能找到对应的类;在指定类中是否存在符合方法的字段描述符以及简单名称所描述的方法和字段............
3、准备
准备阶段是正式为类变量分配内存并设置类变量初始值的阶段。对于非静态的变量,则不会为它们分配内存。
数据类型的初始值: int, byte, char, long, float, double默认初始值为0; boolean为false;reference为null.
对于常量属性(public static final int value=23),在准备阶段直接赋值23.
4、解析
解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。符号引用就是class格式中的CONSTANT_Class_info, CONSTANT_Fieldref_info, CONSTANT_Methodref_info及 CONSTANT_InterfaceMethodref_info的常量,直接引用就是直接指向目录的指针、相对偏移量或一个间接前两位到目标的句柄。有类或接口的解析,字段解析,类方法解析,接口方法解析。
5、初始化
是初始化类变量和其他资源,这里将执行用户的static字段和静态语句块的赋值操作。这个过程执行类构造器<clinit>()方法的过程。
<clinit>()是邮编译器自动收集类中的所有类变量的赋值动作和静态语句块(static{}块)中的语句合并产生的,编译器收集的顺序是由语句在源文件中出现的顺序所决定的。
1)如果类存在父类,并且父类没有被初始化则先对直接父类进行初始化(执行父类的<clinit>()).
2)如果类妆前存在<clinit>()方法,则执行<clinit>()方法。
接口interface不能用static块
类加载器
启动类加载器 Bootstrap ClassLoader,主要负责加载java_home/lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且可以是被拟机识别的类库到虚拟机内存中。
扩展类加载器 Extension ClassLoader:这个加载器由sun.misc.Launcher$ExtClassLoader实现,负责加载java_home/lib/ext目录中,或者被java.ext.dirs系统变量所指定的路径中的类库
应用程序类加载器 Application ClassLoader:也叫系统类加载器。这个类加载器由sun.misc.Launcher$App-ClassLoader实现,主要负责加载classPath路径上的类库,如果应用程序没有自定义自己类加载器,则这个就是默认的类加载器。
这三类加载器,不是父子关系,而是采用组合方式。正常情况下,每个类加在收到类加载请求时,会先调用父加载器进行加载,若父加载器加载失败,则子加载器进行加载。只有父加载器不能加载该类时才会调用子加载器。
如需要加载java.lang.Object类时,不论使用哪个类加载器来加载,会找到根classLoader来加载该类。
原文:http://www.cnblogs.com/zyzl/p/4148997.html