目录
类加载机制
当我们要使用某个类时,如果该类的class文件没有加载到内存是,系统就会通过三个步骤来对该类进行初始化
1.类的加载:将类的class文件读入内存,并为之创建一个java.lang.Class的对象,此过程中由类加载器完成
2.类的连接:将类的数据加载到各个内存区域
3.类的初始化:jvm负责对类进行初始化
深入类加载过程:
类的完整生命周期:加载->连接(验证、准备、解析、初始化)->使用->卸载
1.加载:
1.通过一个类的全限定名来获取其定义的二进制字节流
2.将这个字节流所代表的静态存储结构转化为方法区的运行时的数据结构
3.在堆中生成一个代表这个类的Class对象,作为方法区中这些数据的访问入口
2.连接:
1.验证:(1)文件格式的验证,验证class文件字节流是否符合class文件的格式规范,并且能够被当前版本的虚拟机处理(2)元数据分析:主要是对自己吗描述的信息进行语义分析,以保证其描述的信息符合java语言规范的要求,比如验证这个类是不是有父类等(3)字节码验证,主要是通过数据流和控制流分析,确定程序语义是合法的,符合逻辑的,在元数据验证阶段对数据做出验证后,这个阶段主要对类的方法做出分析,以保证类的方法不会对虚拟机产生威胁(4)符号引用验证:主要是对类自身以外的信息进行校验,确保解析动作能够完成。
2.准备:准备阶段主要为类变量(static)分配内存并设置初始值。这些内存都在方法区分配。(1)类变量(static):会分配内存,但不会对应的分配值,其次实例变量不会分配空间,因为实例变量主要随着对象的实例化一块分配到java堆内存中。(2)初始值:这里的初始值指的是数据类型默认值,而不是代码中被显示赋予的值
3.解析:解析阶段主要是虚拟机将常量池中的符号引用转化为直接引用的过程。(1)符号引用:以一组符号来描述所引用的目标,可以是任何形式的字面量,只要是能无歧义的定位到目标就好。(2)直接引用:直接引用是可以指向目标的指针、相对偏移量或者是一个能直接或间接定位到目标的句柄。
4.初始化:在初始化阶段,主要为类的静态(stitic)变量赋予正确的初始值,JVM负责对类进行初始化,主要对类变量(stitic)进行初始化。
3.使用:
当 JVM 完成初始化阶段之后,JVM 便开始从入口方法开始执行用户的程序代码
4.卸载:
当用户程序代码执行完毕后,JVM 便开始销毁创建的 Class 对象,最后负责运行的 JVM 也退出内存
类加载器分类
从jvm的角度讲只有两种不同的类加载器
1.启动类加载器(Bootstrap ClassLoader):这个类加载器用 C++ 实现,是虚拟机自身的一部分
2.所有其他类的加载器,这些类由 Java 实现,独立于虚拟机外部,并且全都继承自抽象类 java.lang.ClassLoader
从java开发人员角度讲:
1.启动类加载器(Bootstrap ClassLoader): 最顶层的类加载器,负责加载 JAVA_HOME\lib 目录中的,或通过-Xbootclasspath参数指定路径中的,且被虚拟机认可(按文件名识别,如rt.jar)的类。
2.扩展类加载器(Extension ClassLoader)这个类加载器是由 ExtClassLoader(sun.misc.Launcher$ExtClassLoader)实现的。 负责加载 JAVA_HOME\lib\ext 目录中的,或通过java.ext.dirs系统变量指定路径中的类库
3.应用程序类加载器(Application ClassLoader)这个类加载器是由 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的。 也叫做系统类加载器,可以通过getSystemClassLoader()获取,负责加载用户路径(classpath)上的类库。如果没有自定义类加载器,一般这个就是默认的类加载器
类加载器之间的层次关系: 启动类加载器 > 扩展类加载器 > 应用程序类加载器 > 自定义类加载器
双亲委派模型
工作过程:
一个类加载器接受到类加载请求,他自己不会去加载这个请求,而是将这个类加载请求委派给父类加载器,这样一层一层传送,直到到达启动类加载器(Bootstrap ClassLoader)。只有当父类加载器无法加载这个请求时,子加载器才会尝试自己去加载。
好处 :
使得 Java 类随着它的类加载器一起具有一种带有优先级的层次关系,从而使得基础类得到统一。 双亲委派模型很好的解决了各个类加载器加载基础类的统一性问题。即越基础的类由越上层的加载器进行加载
原则:
1.可以避免重复加载,父类已经加载了,子类就不需要再次加载
2.更加安全,很好的解决了各个类加载器的基础类的统一问题,如果不使用该种方式,那么用户可以随意定义类加载器来加载核心api,会带来相关隐患。