Java 中的类加载机制、双亲委派模型

Java 中的类加载机制

加载 验证 准备 解析 初始化。

加载:
1、通过一个类的全限定名来获取其定义的二进制字节流。
2、将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3、在Java堆中生成一个代表这个类的java.lang.Class对象,作为对方法区中这些数据的访问入口。

验证: 为了验证class文件中的字节流符合Java虚拟机的规范,包括文件的格式,元数据验证等。
准备: 为类变量分配内存,并设置类变量初始值,分配的内存在方法区。
解析: 将常量池中的符号引用转为直接引用的过程。符号引用与虚拟机实现的内存布局无关,只是一组符号来描述所引用的目标。class文件中的常量池包括字面量与符号引用(字段的名称和描述符、方法的名称和描述符、类和接口的全限定名)。在class文件中不会保存各个方法字段的最终布局信息,因此这些符号引用不经过转化是无法得到真正的内存入口地址。直接引用与虚拟机实现的内存布局有关,可以是直接指向目标的指针,偏移量或者指向目标的句柄。包括类或接口的解析,字段的解析,类方法的解析,接口方法的解析。此过程主要是静态链接,方法主要为静态方法和私有方法,对于动态链接是在运行时通过动态分派来实现的。
初始化阶段: 该阶段才会真正的开始执行类中定义Java代码。初始化时执行类构造器 clinit()方法的过程,该方法由编译器自动收集类中所有类变量的赋值动作和静态语句块的语句合并产生。且保证子类的clinit调用之前会先执行父类的clinit方法,接口除外,接口的实现类执行clinit()方法时不会执行接口的clinit方法。clinit()方法可以不存在,比如没有静态语句块和类变量。

双亲委派模型

类加载器
Java中的类加载器主要用于实现类的加载。java中的类和类加载器一起唯一确定类在 jvm 中的唯一性。

启动类加载器: 用C++实现,是jvm中的一部分,其他加载器都是用Java实现,是独立于JVM的,主要负责加载 Java Home下的lib目录下的类库或者被-Xbootclasspath参数指定的路径中的类库,应用程序不能直接使用该加载器。
扩展类加载器: 负责加载Java home下的lib/ext下的类或者系统变量java.ext.dirt指定的路径中的类库,开发者可以直接使用该加载器。
应用程序类加载器: 主要负责加载用户指定的路径即classpath下的类库。如果应用程序没有自定义类加载器,默认使用该加载器。

双亲委派模型要求除了顶层的启动类加载器之外,其他的类加载器都有自己的父类加载器,使用组合关系来复用父类加载器。过程为:当用户需要加载器时,首先不会自己去加载这个类,而是首先调用父类加载器,将请求委派给父类加载器,每一层都是如此,因此所有的加载最终都会到达顶层的启动类加载器,只有当父类加载器反馈不能加载,才会将加载的任务给子加载器。 使用双亲委派模型来组织类加载器之间的关系,有一个很明显的好处,就是Java类随着它的类加载器(说白了,就是它所在的目录)一起具备了一种带有优先级的层次关系,这对于保证Java程序的稳定运作很重要。例如,类java.lang.Object类存放在JDK\jre\lib下的rt.jar之中,因此无论是哪个类加载器要加载此类,最终都会委派给启动类加载器进行加载,这边保证了Object类在程序中的各种类加载器中都是同一个类。

发布了109 篇原创文章 · 获赞 2 · 访问量 2917

猜你喜欢

转载自blog.csdn.net/baidu_41592938/article/details/104576973