首页 > 其他分享 >类加载与双亲委派模型(重点!)

类加载与双亲委派模型(重点!)

时间:2024-05-28 23:33:57浏览次数:20  
标签:委派 初始化 java Extension ClassLoader 双亲 JVM 加载

1.1 类的生命周期

类在内存中完整的生命周期:加载-->使用-->卸载。其中加载过程又分为:装载、链接、初始化三个阶段

1.2 类的加载过程(重点,背也要背下来)

当程序主动使用某个类时,如果该类还未被加载到内存中,系统会通过加载、链接、初始化三个步骤来对该类进行初始化。如果没有意外,JVM将会连续完成这三个步骤,所以有时也把这三个步骤统称为类加载。

类的加载又分为三个阶段:

(1)装载(Loading)

将类的class文件读入内存,并为之创建一个java.lang.Class对象。

就是加载全类名,下面细讲,此过程由类加载器完成

(2)链接(Linking)

①验证Verify:确保加载的类信息符合JVM规范,例如:以cafebabe开头,没有安全方面的问题。

②准备Prepare:正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配。

③解析Resolve:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程。

(3)初始化(Initialization)

 执行类构造器<clinit>()方法的过程。类构造器<clinit>()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。

(类构造器是构造类信息的,不是构造该类对象的构造器)。   当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化。虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确加锁和同步。

2.1 类加载器

将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口。

类缓存:标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些Class对象。

2.2类加载器的分类(掌握)

JVM支持两种类型的类加载器,分别为引导类加载器(Bootstrap ClassLoader)自定义类加载器(User-Defined ClassLoader)

从概念上来讲,自定义类加载器一般指的是程序中由开发人员自定义的一类类加载器,但是Java虚拟机规范却没有这么定义,而是将所有派生于抽象类ClassLoader的类加载器都划分为自定义类加载器。无论类加载器的类型如何划分,在程序中我们最常见的类加载器结构主要是如下情况:

(1)启动类加载器(引导类加载器,Bootstrap ClassLoader)

  • 这个类加载使用C/C++语言实现的,嵌套在JVM内部。获取它的对象时往往返回null

  • 它用来加载Java的核心库(JAVA_HOME/jre/lib/rt.jar或sun.boot.class.path路径下的内容)。用于提供JVM自身需要的类。

  • 并不继承自java.lang.ClassLoader,没有父加载器。

  • 出于安全考虑,Bootstrap启动类加载器只加载包名为java、javax、sun等开头的类

  • 加载扩展类和应用程序类加载器,并指定为他们的父类加载器

(2)扩展类加载器(Extension ClassLoader)

  • Java语言编写,由sun.misc.Launcher$ExtClassLoader实现。

  • 继承于ClassLoader类

  • 父类加载器为启动类加载器

  • 从java.ext.dirs系统属性所指定的目录中加载类库,或从JDK的安装目录的jre/lib/ext子目录下 加载类库。如果用户创建的JAR放在此目录下,也会自动由扩展类加载器加载。   

(3)应用程序类加载器(系统类加载器,AppClassLoader)

  • java语言编写,由sun.misc.Launcher$AppClassLoader实现

  • 继承于ClassLoader类

  • 父类加载器为扩展类加载器

  • 它负责加载环境变量classpath或系统属性 java.class.path 指定路径下的类库

  • 应用程序中的类加载器默认是系统类加载器。

  • 它是用户自定义类加载器的默认父加载器

  • 通过ClassLoader的getSystemClassLoader()方法可以获取到该类加载器

3.1双亲委派模型高频面试题

双亲委派其实就发生在“加载环节”第一步,算不上“核心”。

主要就是描述JVM中类加载的过程中,找文件的过程中。

看图:这里是JVM中内置的三个类加载器,负责加载不同的类(重点)

     引导类加载器,Bootstrap ClassLoader      爷爷 

    负责加载标准库

     扩展类加载器(Extension ClassLoader)  父亲

     负责加载扩展目录

  应用程序类加载器(系统类加载器,AppClassLoader) 儿子

  负责加载第三方的库和你自己写的代码类

注:此处的“父子关系”不是通过类的继承表示的(不是父类,子类),而是通过类加载器

中存在一个“parent”这样的字段指向自己的父亲

类似于二叉树的“三叉实现形式”

所以说双亲委派模型本身说法是不正确的,我认为叫"单亲委派模型更好"

模拟加载流程(重点)

列如,给一个类的全类名,这里我给一个我自己写的类,如Java222.Test

加载过程如下

1 . 工作从ApplicationClassLoader开始进行

ApplicationClassLoader并不会立即搜索第三方相关的目录,而是把任务交给自己的父亲来处理

2 .  工作到了Extension ClassLoader

 Extension ClassLoader 也不会立即搜索负责的扩展类目录,也是继续交给自己的父亲来处理

3   工作到了BootstrapClassLoader

 BootstrapClassLoader也想交给自己的父亲来处理,可是它的parent=null,所以只能自己来处理,BootstrapClassLoader开始在标准库里面来搜索这个类

此时,如果在如果在 BootstrapClassLoader中查找到了这个类就直接开始读取文件,查找文件等操作,但是如果在BootstrapClassLoader中查找不到Java222.Test这个类,就会还给自己的儿子来处理这个任务,我们继续往下走

4. 此时工作回到了 Extension ClassLoader

Extension ClassLoader开始在自己负责的扩展类里查找,如果查找到了这个类就直接开始读取文件,查找文件等,如果没找到就交给自己的儿子来处理

5. 工作回到了ApplicationClassLoader

此时ApplicationClassLoader在自己负责的第三方目录里查找,查到就开始读取文件,打开文件,但是找不到,这里就没有儿子了,就会抛出一个ClassNotFoundException的异常

总结:这个过程其实一个不难,有点望父成龙的感觉,但是这是应对一下场景,列如,你在你的代码写了一个类,类的名字和标准库/扩展库的名称冲突了。此时JVM就会保证加载标准库的类而不是你的类,如果标准库的类没有被夹在,而是加载了你自己写,那代码不就崩了吗。

标签:委派,初始化,java,Extension,ClassLoader,双亲,JVM,加载
From: https://blog.csdn.net/weixin_75230545/article/details/139279558

相关文章

  • bert模型数据集加载方式
    数据集构造无论是机器学习还是深度学习对于数据集的构造都是十分重要。现记录一下PyTorch的torch.utils.data.Dataset类的子类。Dataset类是PyTorch框架中用于处理数据的基本组件,它允许用户定义自己的数据集类,以满足特定任务的需求。Dataset是一个抽象基类,用于创建自......
  • 介绍图片懒加载的几种实现方法
    在JavaScript中,懒加载(LazyLoading)主要用于延迟加载资源,例如图片、视频、音频、脚本等,直到它们真正需要时才加载。这样可以提高页面的加载速度和性能。以下是几种常见的JavaScript懒加载实现方式:1.监听滚动事件通过监听滚动事件来实现图片懒加载是一种传统并且常见的方......
  • Dolphinscheduler不重启加载Oracle驱动
    转载自刘茫茫看山问题背景某天我们的租户反馈数据库连接缺少必要的驱动,我们通过日志查看确实是缺少部分数据库的驱动,因为DolphinScheduler默认只带了Oracle和MySQL的驱动,并且需要将pom文件中的test模式去掉才可以在打包的时候引入。我们的任务量比较大,在3.0存在容错机制的情况下......
  • 异步数据加载与绑定设计: AsyncLoadHelper
    在现代应用程序开发中,异步数据加载和管理是一个普遍的需求。本文介绍了一个自定义的异步数据加载工具——AsyncLoadHelper。通过详细的设计和实现介绍,以及结合实际应用示例,展示了AsyncLoadHelper在简化异步操作、提高代码可读性和维护性方面的优势。在开发过程中,异步数据加载常常......
  • vue首屏加载动画打包后失效
    本地环境运行时,没有问题,打包后,加载动画没有效果,尝试修改:extract:false后成功。 加载动画示例:index.html中<linkrel="stylesheet"href="static/css/loading.css"/><body><divid="app"><divid="appLoading"><d......
  • WPF Splash Screen – A New Splash Screen Manager (v20.1) 启动页 闪屏页 初始加载
    WPFSplashScreen–ANewSplashScreenManager(v20.1)(devexpress.com)  WPFTeamBlog RSS06July2020A splashscreen isaneffectivewaytoimproveanapp’suserexperienceduringlengthystartupoperations.Unfortunately,creatinganef......
  • 【scss】基于:empty伪类的空元素回显及加载状态
    mixin.scss/**空内容height:占位高度**/@mixinempty-block($height:220px){display:block;position:relative;width:100%;min-height:$height;//图片高度background-image:url('~@/assets/images/default-img/no-data.svg');background-repeat......
  • spring源码阅读之bean加载过程(一)
    如果想要阅读源码,首先要选择版本,然后将源代码下载到本地,导入idea中,话不多说,直接看步骤吧这里我选择5版本,下载源码默认是main分支,看想学习的分支,比如我切换到5版本,截图如下:  2.安装gradle3.转换源码进idea下载完成后可以看到有个文档叫import-into-idea.md,......
  • java 加载bean 2
    @RequiredArgsConstructor@Component@RequestMapping("/timeLineData")publicclassTimeLineData{ finalCustomSqlServicecustomSqlService; @Inner(false) @PostMapping("/setTimeLine") voidsetTimeLine(@RequestBodyMap<String,Obj......
  • java中的类加载器
    类加载器(ClassLoader)是Java虚拟机(JVM)的一部分,它负责将类文件(.class)加载到内存中,并在运行时为应用程序提供类的定义。类加载器在Java中起着至关重要的作用,因为它们允许Java应用程序在运行时动态加载类,这对于大型和复杂的应用程序尤为重要。本文将深入探讨Java中的类加载器,讨论它......