47.【面试宝典】面试宝典-类加载器及双亲委派

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 【面试宝典】面试宝典-类加载器及双亲委派

前文如上:

39.【面试宝典】面试宝典-redis过期k值回收策略,缓存淘汰策略

40.【面试宝典】面试宝典-redis持久化

41.【面试宝典】面试宝典-redis常用数据类型概述

42.【面试宝典】面试宝典-redis缓存穿透,击穿,雪崩

43.【面试宝典】面试宝典-redis缓存穿透之布隆过滤器

44.【面试宝典】面试宝典-redis分布式锁

45.【面试宝典】面试宝典-另外两种分布式锁

46.【面试宝典】面试宝典-虚拟机类加裁机制

合集参考:面试宝典


文档参考:《深入理解Java虚拟机 JVM高级特性与最佳实践》第3版_周志明

image.png

类加载器


虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到 Java 虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块称为“类加载器”


1.类与类加载器


网络异常,图片无法展示
|

网络异常,图片无法展示
|

网络异常,图片无法展示
|


2.类加载器


网络异常,图片无法展示
|


我们看一下JVM预定义的三种类加载器,当JVM启动的时候,Java缺省开始使用如下三种类型的类加载器:


启动(Bootstrap)类加载器: 引导类加载器是用 本地代码实现的类加载器,它负责将 /lib下面的核心类库-Xbootclasspath选项指定的jar包等虚拟机识别的类库 加载到内存中。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以 不允许直接通过引用进行操作。

扩展(Extension)类加载器: 扩展类加载器是由Sun的ExtClassLoader(sun.misc.Launcher$ExtClassLoader)实现的,它负责将 /lib/ext或者由系统变量-Djava.ext.dir指定位置中的类库 加载到内存中。开发者可以直接使用标准扩展类加载器。

系统(System)类加载器: 系统类加载器是由 Sun 的 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的,它负责将 用户类路径(java -classpath或-Djava.class.path变量所指的目录,即当前类所在路径及其引用的第三方类库的路径)下的类库 加载到内存中。开发者可以直接使用系统类加载器。

自定义类加载器:开发人员可以通过继承 java.lang.ClassLoader类的方式实现自己的类加载器,以满足一些特殊的需求。一般来说,自己开发的类加载器只需要覆写 findClass(String name)方法即可。java.lang.ClassLoader类的方法loadClass()封装了前面提到的代理模式的实现。该方法会首先调用findLoadedClass()方法来检查该类是否已经被加载过;如果没有加载过的话,会调用父类加载器的loadClass()方法来尝试加载该类;如果父类加载器无法加载该类的话,就调用findClass()方法来查找该类。因此,为了保证类加载器都正确实现代理模式,在开发自己的类加载器时,最好不要覆写 loadClass()方法,而是覆写 findClass()方法


3.java.class.ClassLoader类


(1)作用:

  • java.lang.ClassLoader类的基本职责就是根据一个指定的类的名称,找到或者生成其对应的字节代码,然后从这些字节代码中定义出一个Java类,即java.lang.Class类的一个实例。
  • ClassLoader还负责加载 Java 应用所需的资源,如图像文件和配置文件等。

(2)常用方法:

  • getParent() 返回该类加载器的父类加载器。
  • loadClass(String name) 加载名称为 name的类,返回的结果是java.lang.Class类的实例。 此方法负责加载指定名字的类,首先会从已加载的类中去寻找,如果没有找到;从parent ClassLoader[ExtClassLoader]中加载;如果没有加载到,则从Bootstrap ClassLoader中尝试加载(findBootstrapClassOrNull方法), 如果还是加载失败,则自己加载。如果还不能加载,则抛出异常ClassNotFoundException。
  • findClass(String name) 查找名称为 name的类,返回的结果是java.lang.Class类的实例。
  • findLoadedClass(String name) 查找名称为 name的已经被加载过的类,返回的结果是 java.lang.Class类的实例。
  • defineClass(String name, byte[] b, int off, int len) 把字节数组 b中的内容转换成 Java 类,返回的结果是java.lang.Class类的实例。这个方法被声明为 final的。
  • resolveClass(Class<?> c) 链接指定的 Java 类。

4.双亲委派机制


网络异常,图片无法展示
|


5.为什么使用双亲委派


使用双亲委派模型来组织类加载器之间的关系,有一个显而易见的好处就是 Java 类随 着它的类加载器一起具备了一种带有优先级的层次关系。例如类 java.lang.Object ,它存放在 rt.jar 之中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此 Object 类在程序的各种类加载器环境中都是同一个类。


相反,如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户自己编写了一个称为 java.lang.Object 的类,并放在程序的 ClassPath 中,那系统中将会出现多个不同的 Object 类, Java 类型体系中最基础的行为也就无法保证,应用程序也将会变得一片棍混乱。如果感兴趣的话,可以尝试去编写一个与 rt.jar 类库中已有类重名 Java 类, 将会发现可以正常编译,但永远无法被加载运行


双亲委派模型对于保证 Java 程序的稳定运作很重要 ,但它的实现却非常简单,实现双 委派的代码都集中在 java.lang. ClassLoader loadClass ()方法之中,如下图所示,逻辑清晰易懂:先检查是否已经被加载过,若没有加载则调用父加载器的 loadClass() 方法,若父加载器为空则默认使用启动类加载器作为父加载器,如果父类加载失败,抛出 Class Not FoundException 异常后,再调用自己的 findClass ()方法进行加载。


网络异常,图片无法展示
|


公众号,感谢关注

网络异常,图片无法展示
|


相关文章
|
12月前
|
Arthas 测试技术
【面试题精讲】JVM-类加载器-使用Arthas查看类加载器
【面试题精讲】JVM-类加载器-使用Arthas查看类加载器
【面试题精讲】JVM-类加载器-使用Arthas查看类加载器
|
12月前
【面试题精讲】JVM-类加载器-应用场景
【面试题精讲】JVM-类加载器-应用场景
|
1月前
|
安全 Java 应用服务中间件
JVM常见面试题(三):类加载器,双亲委派模型,类装载的执行过程
什么是类加载器,类加载器有哪些;什么是双亲委派模型,JVM为什么采用双亲委派机制,打破双亲委派机制;类装载的执行过程
JVM常见面试题(三):类加载器,双亲委派模型,类装载的执行过程
|
12月前
|
存储 缓存 前端开发
【面试题精讲】JVM-类加载器
【面试题精讲】JVM-类加载器
|
12月前
|
Java
【面试题精讲】JVM-类加载器-Java中的默认类加载器
【面试题精讲】JVM-类加载器-Java中的默认类加载器
|
5月前
|
前端开发 IDE Java
大厂面试题详解:有几种类型的类加载器,都具体是干什么的
字节跳动大厂面试题详解:有几种类型的类加载器,都具体是干什么的
79 0
|
开发框架 前端开发 Java
JVM面试专题-JVM中你知道的类加载器以及作用
JVM面试专题-JVM中你知道的类加载器有哪些?作用是什么?分别用来加载什么文件?什么内容的呢?
79 1
|
12月前
|
前端开发 Java C++
【面试题精讲】JVM-打破双亲委派机制-自定义类加载器
【面试题精讲】JVM-打破双亲委派机制-自定义类加载器
|
12月前
|
Java 数据库 数据安全/隐私保护
【面试题精讲】JVM-类加载器-类加载器分类
【面试题精讲】JVM-类加载器-类加载器分类
|
12月前
|
前端开发 Java 数据库连接
【面试题精讲】JVM-类加载器-扩展类加载器
【面试题精讲】JVM-类加载器-扩展类加载器