java的类加载机制
java程序在运行时,会调用一个入口函数来调用系统相关的功能,这些功能有可能封装在不同的class文件中,java的类加载机制会根据程序需要将class文件动态加载到jvm内存当中。java的类加载机制主要分为3个阶段:加载-> 链接 -> 初始化。
加载: 将字节码数据从不同的数据源读取到jvm中,并映射为jvm认可的数据结构(class对象),作为方法区这个类各种数据的访问入口;这里的数据源可能是各种各样的形态,jar文件、class文件、网络数据源等。jvm并没有明确规定class文件加载到jvm内存的时机,交给虚拟机的具体实现自由把握。
链接:链接就是将原始的类定义信息平滑转化入jvm内存的过程,链接可以细分为3个步骤:验证、准备和解析。
-
验证:验证字节码信息是否符合java虚拟机的规范,防止恶意危害jvm的运行
-
准备:初始化类中默认变量的系统默认值(注意这里并不是按照程序员的意愿对变量进行赋值)
-
解析:将符号引用转化成直接引用的过程;符号引用以一组符号来描述引用的目标,符号可以是任何形式的字面量,只要能无歧义地定位到目标即可,与jvm的内存布局无关。而直接引用是与jvm内存布局相关的,直接引用的目标必须存在于内存当中。
直接引用可以是:
(1)直接指向目标的指针(比如,指向“类型”【Class对象】、类变量、类方法的直接引用可能是指向方法区的指针) (2)相对偏移量(比如,指向实例变量、实例方法的直接引用都是偏移量) (3)一个能间接定位到目标的句柄
初始化:初始化是类记载过程的最后一步,前面的几个步骤除了用户可以自定义类加载器以外,其它动作全部由虚拟机主导和控制,到了初始化阶段才真正根据程序员的主观意识去初始化类变量和其他资源。初始化阶段是执行类构造器方法clinit()的过程,clinit()方法是由编译器收集类变量的赋值语句和静态语句块合并而成的。