Java中类加载器和双亲委派机制
Posted Ferron Zhu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中类加载器和双亲委派机制相关的知识,希望对你有一定的参考价值。
1、JVM中的类加载器
1.1、概述
-
首先,我们得先明确一点,JVM是位于操作系统之上的一个Java虚拟机。
-
我们都知道,JVM中很重要的一个组件就是类加载器,.java文件经过编译器编译成字节码(.class)文件之后,经过JVM中的类加载器加载后变成一个个Class。由于Java是单例模式且Class是模板,所以只要Class创建之后全局唯一,Class经过实例化(new)之后变成一个个不同且具体的实例化对象。
-
Class实例化后创建的对象都存储在堆内存中,而其引用而会出现在栈空间和本地方法栈空间中。
1.2、类加载器分类
- 用户自己定义的类加载器
- 应用程序类加载器(system class loader):也称系统类加载器,如果用户自己没有定义类加载器时,这是系统默认的类加载器,用来加载当前classpath下的类。它的父类是拓展类加载器。
- 拓展类加载器(extend class loader):这是加载JRE的拓展目录,父类为null。
- 启动类加载器(Boostrap class loader):这是用来用来加载 Java 的核心类,并不继承自 java.lang.ClassLoader
1.3、类加载器流程
正向过程:
反向过程:
- 注意:如果用户没有定义类加载器,则
.getClassLoader().getParent()
返回的结果是应用程序类加载器,至于为什么类加载器的加载过程是这样,这就得介绍Java中的类加载机制:双亲委派机制
2、双亲委派机制
- 上图为类加载器之间关系,由上图可知,除了应用程序类加载器以为,所有的类加载器都有父类加载器。
- 我们假设用户定义了一个类加载器,每次进行类加载时,首先类加载是使用用户定义的类加载器,而在用户定义的类加载器中,会默认把类加载的任务委托给其父类,也就是应用程序类加载器。
- 应用程序类加载器同样会把类加载的任务委托给其父类也就是拓展类加载器,最终所有的类加载任务都会到启动类加载器。
- 只有当启动类加载器加载不了拓展类委托加载的类时,拓展类加载器才会自己去加载类;而当拓展类加载不了应用程序类加载委托加载的类时,应用程序类加载器才会自己去加载类。
- 在网上找到了一个很好的双亲委派机制的比喻:可以把每个类加载都想成一个大懒汉,每次让他办事时他都让爸爸代办。没想到爸爸也是个大懒汉,于是爸爸也让他的爸爸代办。这是到了爷爷那里,爷爷也很懒,但是他没有爸爸了,于是只能一边抱怨一边干,然后发现自己做不了,又骂骂咧咧的把活儿交给了自己的儿子,然后爸爸开始干活,发现自己也不能完成这个任务,于是他也是骂骂咧咧的把活交给了儿子,儿子挨了一顿骂,然后开始干活,经过了1小时的苦干,这个活儿终于完事了。
- 例如:我们自己写了一个
Student
类,通过双亲委派机制,最终加载该类的类加载器是应用程序类加载器;但如果我们自己定义了一个java.lang.String
类,通过双亲委派机制,最终加载该类的类加载器是启动类加载器,加载的是JRE已经写好的java.lang.String
类,这也就意味着我们自己写的java.lang.String
类根本不会被加载,没有一点用处!
双亲委派机制的优势:
- 定义了类加载的层次关系,防止了一个类被重复加载
- 不管什么类最先都由启动类加载器进行加载,防止出现上面系统中核心类被用户写的类所覆盖的问题,保护了Java核心API的一致性。
载,防止出现上面系统中核心类被用户写的类所覆盖的问题,保护了Java核心API的一致性。
以上是关于Java中类加载器和双亲委派机制的主要内容,如果未能解决你的问题,请参考以下文章