java八股文面试[JVM]——双亲委派模型

news/2025/2/12 13:21:36/

在这里插入图片描述

 

1.当AppClassLoader去加载一个class时,它首先不会自己去尝试加载这个类,而是把类加载请求委托给父加载器ExtClassLoader去完成。
2.当ExtClassLoader去加载一个class时,它首先也不会去尝试加载这个类,而是把类加载请求委托给父加载器BootstrapClassLoader去完成。
3.如果BootstrapClass加载失败(例如在JAVA_HOME/jre/lib里未找到该class),就会使用ExtClassLoader来尝试加载。
4.如果使用ExtClassLoader加载失败(例如在JAVA_HOME/jre/lib/ext里未找到该class),就会使用AppClassLoader来尝试加载。如果AppClassLoader也加载失败,则会抛出异常ClassNotFoundException

从代码层面了解几个Java中定义的类加载器及双亲委派模型的实现,他们的类图关系如下。

在这里插入图片描述

从图可以看出顶层的类加载器是抽象类abstract ClassLoader,其后所有的类加载器都继承自ClassLoader(不包括启动类加载器)。为了更好的理解双亲委派模型,ClassLoader源码中的loadClass(String)方法该方法加载指定名称(包括包名)的二进制类型,该方法在jdk1.2后不建议用户重写但是可以直接调用该方法。loadClass()方法是ClassLoader类自己实现的,该方法中的逻辑就是双亲委派模式的实现loadClass(String name, boolean resolve)是一个重载方法,resolve参数代表是否生成Class对象的进行解析相关的操作,源码分析如下。

双亲委派模型意义总结来讲就是:
1.系统类防止内存中出现多份相同的字节码。
2.保证Java程序安全稳定运行。

加载类的三种方式

到这里,相信大家都对类加载器和类的加载都有一定的了解了,那么你知道嘛?常见的加载类的方式有三种。

  1. 静态加载:也就是使用new关键字来创建实例对象,
  2. 动态加载:使用Class.forName()动态加载(反射加载类型),然后调用类的newInstance()方法实例化对象。
  3. 动态加载:通过类加载器的loadClass()方法来加载类,然后调用类的newInstance()方法实例化对象。
三种方式的区别
  1. 第一种和第二种方式使用的类加载器是相同的,都是当前类加载器(this.getClass().getClassLoader()),第三种方式需要用户指定类加载器。
  2. 如果需要在当前类路径以外加载类,则只能使用第三种方式,第三种方式加载的类与当前类分属不同的命名空间
  3. 第一种方式是静态加载,第二种和第三种是动态加载。
两种异常(Exception)
  1. 静态加载的时候如果在运行环境中找不到要初始化的类,抛出的是NoClassDefFoundError。它在Java的异常体系中是一个error
  2. 动态加载的时候如果运行环境中找不到要初始化的类,抛出的是ClassNotFoundException。它在Java的异常体系中是一个checked异常
Class.forName与ClassLoader.loadClass的区别

首先,我们必须要明白类加载机制的三个主要过程是:加载–>连接–>初始化。

  • Class.forName():除了将类的.class文件加载到JVM中之外,还对类进行解释,执行类中的static块。
  • ClassLoder.loadClass():只是将类的.class文件加载到JVM中,并不会执行类的static块,只有在newInstance才会执行static块
  • Class.forName(name, initialize, loader):带参函数也可控制是否加载static块。并且只有调用了newInstance()方法采用调用构造函数。创建类的对象 。

下面我们写下代码,加深一下影响。

public class Demo {static {System.out.println("正在加载Demo...");}
}
import java.lang.Class;public class TestDemo {public static void main(String[] args) throws ClassNotFoundException {//1.使用 Class.forName()加载类,默认执行static块。Class.forName("Demo");//获得当前类的类加载器ClassLoader classLoader = Test.class.getClassLoader();//2.使用 Class.forName()加载类,并指定ClassLoader。初始化时不会执行static块。Class.forName("Demo", false, classLoader);//3.使用ClassLoader类的loadClass()方法加载类,不会执行初始化classLoader.loadClass("Demo");}
}

只有第一行代码输出了

 

知识来源:

【基础】双亲委派模型_哔哩哔哩_bilibili 

深入理解Java类加载器(ClassLoader)

 


http://www.ppmy.cn/news/1061433.html

相关文章

抖音seo短视频矩阵系统源码开发源代码分享--开源-可二开

适用于抖音短视频seo矩阵系统,抖音矩阵系统源码,短视频seo矩阵系统源码,短视频矩阵源码开发,支持二次开发,开源定制,招商加盟SaaS研发等。 功能开发设计 1. AI视频批量剪辑(文字转语音&#x…

人力资源小程序的设计与开发步骤

在当前信息化时代,小程序成为了各行各业提升用户体验和服务效率的重要渠道。人力资源部门也可以通过定制开发人力资源小程序来提升招聘、培训、员工福利等方面的工作效率。接下来,我们将介绍人力资源小程序定制系统开发的具体流程。 首先,我们…

机器学习基础之《分类算法(5)—朴素贝叶斯算法原理》

一、朴素贝叶斯算法 1、什么是朴素贝叶斯分类方法 之前用KNN算法,分类完直接有个结果,但是朴素贝叶斯分完之后会出现一些概率值,比如: 这六个类别,它都有一定的可能性 再比如,对文章进行分类:…

Python案例|Matplotlib库实现的数据分析

数据展示是数据分析和挖掘中的重要环节,通过图形的形式可以直观、清晰地呈现数据内在的规律。 本文所用数据采用上一篇案例实现后的数据表,数据存储在newbj_lianJia.csv文件中,具体代码如下。 import pandas as pd #导入库 import matplot…

【51单片机】EEPROM-IIC实验(按键控制数码管)

目录 🎁I2C总线 ​编辑 🎁代码 🏳️‍🌈main.c 🏳️‍🌈i2.c 🎆代码分析 🎁I2C总线 I2C总线是Philips公司在八十年代初推出的一种串行、半双工的总线,主要用于近距…

题解:ABC280D - Factorial and Multiple

题解:ABC280D - Factorial and Multiple 题目 链接:Atcoder。 链接:洛谷。 难度 算法难度:B。 思维难度:A。 调码难度:A。 综合评价:普及/提高-。 算法 质因数分解数论。 思路 这题…

excel下载后文件名称不对

正确写法 String headerValue String.format("attachment; filename\"%s\";", fileName "_" dateStr ".xlsx");// 这样就可以了response.setHeader("content-disposition", headerValue);// 或者这样response.setHeader(…

一文学会lua脚本

文章目录 0.前言背景应用 1. 学习大纲1. 学习基本语法:2. 理解函数和模块:3. 深入数据结构:4. 高级特性和技巧:5. 实践项目: 2. Lua脚本2.1 学习基本语法2.2 理解函数和模块2.3 深入数据结构2.4 高级特性和技巧 3. 高级…