JVM面试题-类加载顺序、双亲委派、类初始化顺序(详解)

news2024/11/25 23:47:31

类加载器

JVM只会运行二进制文件,类加载器的作用就是将字节码文件加载到JVM中,从而让Java程序能够启动起来。

类加载负责执行类加载,去磁盘进行识别,识别完后加载到内存

类加载器的种类:

从上往下

  • 启动类加载器:用来加载java核心类库,无法被java程序直接引用,加载的是JAVA_HOME/jre/lib;

  • 扩展类加载器:用来加载java的扩展库, java的虚拟机实现会提供一个扩展库目录,加载的是JAVA_HOME/jre/lib/ext;

  • 应用类加载器:它根据java的类路径来加载类,一般来说,java应用的类都是通过它来加载的,加载的是CLASSPATH;

  • 自定义类加载器:平时用的不多,由java语言实现,继承自AppClassLoader;

双亲委派

加载某一个类,先委托上一级的加载器进行加载,如果上级加载器也有上级,则会继续向上委托,如果该类委托上级没有被加载,子加载器尝试加载该类。

好处:

  1. 可以避免某一个类被重复加载,当父类已经加载后则无需重复加载,保证唯一性。

  2. 为了安全,保证类库API不会被修改。

    例如:用户自己写一个String类的话,执行main方法会报错,因为同名的String类已经被加载了,且这个类里面没有main方法,所以报错,这样就保证了不会让别人修改java的核心API库。

能不能自己写一个类,也叫java.lang.String

可以,但是即使你写了这个类,也没有用,这个问题涉及到加载器的委托机制,层层调用,最底下才是我们自定义的类,Java虚拟机会将java.lang.String类的字节码加载到内存中。

为什么只加载系统通过的java.lang.String类而不加载用户自定义的java.lang.String类呢?

因加载某个类时,优先使用父类加载器加载需要使用的类。如果我们自定义了java.lang.String这个类, 加载该自定义的String类,该自定义String类使用的加载器是AppClassLoader,根据优先使用父类加载器原理,一直往上走,最后在启动类加载器中加载了String类。所以,用户自定义的java.lang.String不被加载,也就是不会被使用。

破坏双亲委派

第一破坏:

我们可以重写ClassLoader的loadClass方法,但是双亲委派的逻辑就是存在于这个方法,重写就会破坏

所以JDK1.2之后引入了findClass方法,重写这个方法而不是loadClass

第二次破坏:

各种数据库,JDK提供接口给他们,他们按照接口实现自己的类库,但调用JDK接口时会引起,接口中的类会引起第三方类库的加载,不符合自上而下的加载机制,出现父类加载器请求子类加载器去完成类加载的动作,

SPI spi机制是一种服务发现机制。它通过在 ClassPath 路径下的 META-INF/services 文件夹查找文件,自动加载文件里所定义的类。这一机制为很多框架扩展提供了可能,比如在JDBC中就使用到了SPI机制。

原生的JDBC中 Driver 驱动本身只是一个接口,并没有具体的实现,具体的实现是由不同数据库厂商去实现的。原生的JDBC中的类是放在 rt.jar 包的,是由启动类加载器进行类加载的,在JDBC中的 Driver 类中需要动态加载不同数据库类型的 Driver 类,而 mysql-connector-.jar 中的 Driver 类是用户自己写的代码,那启动类加载器肯定是不能进行加载的,于是乎,这个时候就引入SPI,程序就可以把原本需要由启动类加载器进行加载的类,由应用程序类加载器去进行加载了。

2、Tomcat Tomcat为什么不使用默认的双亲委派模型?

Tomcat 作为一个 web 容器,存在以下使用场景:

1、部署两个应用程序,不同的应用程序可能会依赖同一个第三方类库的不同版本,不能要求同一个类库在同一个服务器只有一份,因此要保证每个程序能使用不同版本的依赖

2、应用程序的类库都是独立的,保证相互隔离;

3、部署在同一个 web 容器中相同的类库相同的版本可以共享;

4、容器也有自己依赖的类库,不能与应用程序的类库混淆。基于安全考虑,应该让容器的类库和程序的类库隔离开来;

2.2、Tomcat 如何实现自己的类加载机制? Tomcat 自己实现了自己的类加载器:

CommonLoader:Tomcat最基本的类加载器,加载路径中的 class 可以被Tomcat容器本身以及各个 Webapp 访问;

CatalinaLoader:Tomcat容器私有的类加载器,加载路径中的 class 对于 Webapp 不可见;

SharedClassLoader:各个 Webapp 共享的类加载器,加载路径中的 class 对于所有 Webapp可见,但是对于Tomcat容器不可见;

WebappClassLoader:各个 Webapp 私有的类加载器,加载路径中的 class 只对当前 Webapp可见;

JspClassLoader:每一个JSP文件对应一个Jsp类加载器。

 

从图中的委派关系中可以看出:

CommonClassLoader 能加载的类都可以被 CatalinaClassLoader 和 SharedClassLoader 使用,从而实现了公有类库的共用; CatalinaClassLoader 和 Shared ClassLoader 自己能加载的类则与对方相互隔离; WebAppClassLoader 可以使用 SharedClassLoader 加载到的类,但各个WebAppClassLoader 实例之间相互隔离; JasperLoader 的加载范围仅仅是这个JSP文件所编译出来的那一个 .Class 文件,它出现的目的就是为了被丢弃:当Web容器检测到JSP文件被修改时,会替换掉目前的 JasperLoader 的实例,并通过再建立一个新的 JasperLoader 来实现JSP文件的热插拔功能。

类加载 过程

虚拟机把描述类的数据加载到内存里面,并对数据进行校验、解析和初始化,最终变成可以被虚拟机直接使用的class对象;

加载--验证--准备--解析--初始化--使用--卸载

  1. 加载:通过全类名获取类的二进制流,然后吧二进制数据流解析成静态数据结构 存储 在方法区,并在堆中生成一个便于用户调用的java.lang.Class类型的对象

  2. 验证:1.验证class文件的格式是够正确。2.检查是否存在自己要使用的其他类或者方法。

  3. 准备:为类的静态变量分配内存,并初始化值

  4. 解析:将类,接口、字段和方法符号引用转为直接引用

    方法中调用了其他方法,方法名可以理解为符号引用,而直接引用就是使用指针直接指向方法

    比如:假设一个类A被编译成class文件,并且A引用了B,在编译阶段,A就需要一个字符串去记录B的地址,字符串就叫符号引用,在运行时,A类被加载,但是B未被加载,那么将加载B,此时A的符号引用会被替换成B的实际地址,这时就是直接引用

  5. 初始化:就是对类的静态变量,静态代码块执行初始化操作。具体初始化顺序,看下面。

  6. 使用:当我们调用静态类成员信息,比如静态字段、静态方法的时候就是使用了,还有用 new 关键字创建实例也是使用。

  7. 卸载:当用户程序代码执行完毕后,JVM便开始销毁创建的Class对象。

类初始化 顺序

主要是下面几个要点、规则

  1. 先父再子。如果初始化一个类的时候,其父类尚未初始化,则优先初始化其父类。

  2. 自上而下。如果同时包含多个静态变量和静态代码块,则按照自上而下的顺序依次执行。

  3. 懒惰性质。不是所有的类都会在程序启动时立即初始化,而是根据实际需要进行初始化。例如:如果直接用子类调用父类的属性,父类会初始化,子类不会。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1023900.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity的配置文件在安卓路径下使用的方法

Unity的配置文件在安卓路径下使用的方法 前言 之前我做过的很多使用配置文件的Unity项目,后面的有些项目也有在安卓路径下读取json文件的需求。这几天有个需求是获取在安卓路径下配置文件里的数据,我在网上查了一些案例,简单实现了这个需求…

swift 约束布局

添加约束布局 背景图瀑全屏 如何三等分 外面view容器没有约束

Laravel Swagger 使用完整教程

Swagger 使用 一、Swagger 基础1、 什么是Swagger2、 安装过程1 、composer安装2、添加服务提供者,引导框架运行时加载,在 app 配置文件,providers 选项中添加(laravel 5以上忽略此步骤)3、配置完成后,通过输入命令 **php artisan…

QT记事本+登陆界面的简单实现

主体头文件 #ifndef JSB_H #define JSB_H#include <QMainWindow> #include <QMenuBar>//菜单栏 #include <QToolBar>//工具栏 #include <QStatusBar>//状态栏 #include <QTextEdit>//文本 #include <QLabel>//标签 #include <QDebug&g…

什么样的应用程序适合使用Flutter开发桌面?

桌面应用开发的现状 在过去&#xff0c;桌面应用程序的开发通常需要使用特定于操作系统的工具和语言&#xff0c;如C、C#、Java等。这导致了高昂的开发成本和维护困难。尽管有一些跨平台桌面开发工具&#xff0c;如Electron和Qt&#xff0c;但它们在性能、用户体验和开发效率方…

Linus Torvalds接受来自微软的Linux Hyper-V升级

微软最近推送了一些变更&#xff0c;旨在改进即将发布的 Linux 内核 6.6 版本对 Hyper-V 的支持。这些改进包括在 Hyper-V 上支持 AMD SEV-SNP guest 和 Intel TDX guest。除了这两项&#xff0c;还有其他一些升级&#xff0c;如改进了 VMBus 驱动程序中的 ACPI&#xff08;高级…

阿里云产品试用系列-负载均衡 SLB

阿里云负载均衡&#xff08;Server Load Balancer&#xff0c;简称SLB&#xff09;是云原生时代应用高可用的基本要素。通过将流量分发到不同的后端服务来扩展应用系统的服务吞吐能力&#xff0c;消除单点故障并提升应用系统的可用性。阿里云SLB包含面向4层的网络型负载均衡NLB…

Flink TaskManger 内存计算实战

Flink TaskManager内存计算图 计算实例 案例一、假设Task Process内存4GB。 taskmanager.memory.process.size4096m 先排减JVM内存。 JVM Metaspace 固定内存 256mJVM Overhead 固定比例 process * 0.1 4096 * 0.1 410m 得到 Total Flink Memory 4096-256-410 3430m 计…

Palantir的“英伟达时刻”即将到来

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 总结 &#xff08;1&#xff09;由于投资者对生成式人工智能的兴趣持续增加&#xff0c;Palantir的股价一直在上涨。 &#xff08;2&#xff09;Palantir已经连续三个季度实现了GAAP盈利&#xff0c;并将很快有资格被纳入标…

接口幂等性最佳实践--redis+注解

文章目录 一、概念二、常见解决方案三、本文实现四、实现思路五、项目简介六、代码实现1.pom2.JedisUtil3.自定义注解ApiIdempotent4.ApiIdempotentInterceptor拦截器5.TokenServiceImpl6.TestApplication 七、测试验证1.获取token的控制器TokenController2.TestController, 注…

Postman应用——Headers请求头设置

文章目录 Header设置Header删除或禁用Header批量编辑Header预设添加 一般在接口需要校验签名时&#xff0c;Headers请求头用来携带签名和生成签名需要的参数&#xff0c;在Postman也可以设置请求头在接口请求时携带参数。 Header设置 说明&#xff1a; Key&#xff1a;Header…

睿趣科技:新手商家如何做好抖音店铺

抖音&#xff0c;作为全球热门的社交媒体平台之一&#xff0c;不仅仅是分享有趣视频的地方&#xff0c;也是许多商家拓展业务的黄金平台。对于新手商家来说&#xff0c;如何在抖音上建立一个成功的店铺是一项重要的任务。以下是一些关于如何做好抖音店铺的建议。 明确你的目标和…

STM32实现PMBus从机程序

最近在野火的STM32F103VET6开发板上实现PMBus从机程序&#xff0c;这个程序参考了以下这篇博客的关于使用中断法实现I2C从机程序&#xff1a;STM32设置为I2C从机模式_iic从机_柒壹漆的博客-CSDN博客 &#xff0c;实测这个程序是可以正常运行的&#xff0c;感谢博主的分享&#…

Flink 类型机制 及 Stream API和Table API类型推断和转换

注&#xff1a;本文使用flink 版本是0.13 一、类型体系 Flink 有两大API &#xff08;1&#xff09;stream API 和 &#xff08;2&#xff09;Table API ,分别对应TypeInformation 和 DataType类型体系。 1.1 TypeInformation系统 TypeInformation系统是使用Stream一定会用…

【Linux】:Kafka组件介绍

目录 环境简介 一、消息 二、主题 三、分区 四、副本 五、生产者 六、消费者 七、消费者组 八、offsets【偏移量】 环境简介 Linux内核&#xff1a;Centos7 Kafka版本&#xff1a;3.5.1 执行命令的目录位置&#xff1a;Kafka安装目录的bin目录下&#xff1a;/usr/loca…

uvm源码解读-sequence,sequencer,driver三者之间的握手关系1

1.start item 1.start_item();sequencer.wait_for_grant(prior);this.pre_do(1);需要指出&#xff0c;这里明确说明了wait_for_grant和send_request之间不能有任何延迟&#xff0c;所以在mid_do这个任务里千万不能有任何延迟。 task uvm_sequencer_base::wait_for_grant(uvm…

MySQL进阶篇2-索引的创建和使用

索引 mkdir mysql tar -xvf mysqlxxxxx.tar -c myql cd mysql rpm -ivh .....rpm yum install openssl-develsystemctl start mysqldgerp temporary password /var/log/mysqld.logmysql -u root -p mysql> show variables like validate_password.% set global validate_…

maven本地安装jar包

在实际开发中&#xff0c;有些jar包不能通过公共库下载&#xff0c;只能本地安装。可以按照以下步骤操作&#xff1a; 1、安装命令&#xff1a; mvn install:install-file -DgroupIdcom.chinacreator.sm -DartifactIdfbm-sm-common -Dversion0.0.1 -Dpackagingjar -Dfile../n…

基于Java+SpringBoot+Vue+协同过滤算法的电影推荐系统(亮点:智能推荐、协同过滤算法、在线支付、视频观看)

协同过滤算法的电影推荐系统 一、前言二、我的优势2.1 自己的网站2.2 自己的小程序&#xff08;小蔡coding&#xff09;2.3 有保障的售后2.4 福利 三、开发环境与技术3.1 MySQL数据库3.2 Vue前端技术3.3 Spring Boot框架3.4 微信小程序 四、功能设计4.1 主要功能描述 五、系统实…

微服务学习(七):docker安装Mysql

微服务学习&#xff08;七&#xff09;&#xff1a;docker安装Mysql 1、拉取镜像 docker pull mysql2、查看安装的镜像 docker images3、安装mysql docker run -p 3306:3306 --name mysql \ -v /mydata/mysql/log:/var/log/mysql \ -v /mydata/mysql/data:/var/lib/mysql \…