当前位置: 首页 > news >正文

深入JVM:类加载器和双亲委派模型

目录

  • 1. 什么是类加载器
  • 2. 类加载器的类型
  • 3. 双亲委派模型
  • 4. 类装载的过程
      • 加载
      • 验证
      • 准备
      • 解析
      • 初始化
      • 使用
      • 卸载

1. 什么是类加载器

如果想要了解什么是类加载器就需要清楚一个Java文件是如何运行的。我们可以看下图:

首先要知道操作系统是不能直接运行Java文件的,所以就需要通过JVM将Java文件转换为操作系统可以运行的文件类型,步骤如下:

  • 类加载器把Java代码转换为字节码文件
  • 运行时数据区将字节码文件加载到内存中,而字节码文件只是JVM的一套指令集规范,并不能直接交给底层操作系统来执行,而是需要有执行能力的执行引擎来运行
  • 执行引擎将字节码翻译为底层系统指令,再交给CPU来执行,而这个时候需要调用其它语言的本地库接口来实现整个程序的功能

JVM只会运行二进制文件,而类加载器(ClassLoader)的主要作用就是将字节码文件加载到JVM 中 ,从而让Java程序能够启动起来。现有的类加载器基本上都是 java.lang.ClassLoader的子类,该类的只要职责就是用于将指定的类找到或生成对应的字节码文件,同时类加载器还会负责加载程序所需要的资源

2. 类加载器的类型

类加载器根据各自的加载范围不同,进行了划分主要是四种:

  • 启动类加载器:这个类并不继承ClassLoader类,其中是由C++编写实现。用于加载JAVA_Home/jre/lib目录下的类库
  • 扩展类加载器:该列是ClassLoader的子类,主要是加载JAVA_HOME/jre/lib/ext目录中的类库
  • 应用类加载器:该类时ClassLoader的子类,主要是用于加载classPath下的类,也就是加载开发者自己编写的Java类
  • 自定义类加载器:开发者自定义类继承ClassLoader,实现自定义类加载规则

上述三种类加载器的层次结构如下如下:

而类加载器的体系不是继承关系的,而是委派体系,类加载器首先会到自己的父亲中查找类和资源,如果找不到才回到自己的本地进行查找。类加载器的委托行为动机是为了避免相同的类被多次加载

3. 双亲委派模型

如果一个类加载器在接到加载类的请求时,它首先不会自己尝试去加载这个类, 而是把这个请求任务委托给父类加载器去完成,依次递归,如果父类加载器可以 完成类加载任务,就返回成功;只有父类加载器无法完成此加载任务时,才由下一级去加载

那么为什么会需要使用双亲委派模型呢?

  • 通过双亲委派机制可以避免某一个类被重复加载,当父类已经加载后则无需重复加载,保证唯一性
  • 为了安全,保证类库API不会被修改

这里解释一下如何保证类库的API不会被修改:当我们创建一个类String的时候,由于在Java中本身就存在String类,所以使用双亲委派模型的时候,在启动类加载器就会加载Java中的String类,而不会使用应用类加载器进行加载。

public class String {public static void main(String[] args) {System.out.println("demo info")}
}

此时执行main函数,会出现异常,在类 java.lang.String 中找不到 main 方法

出现该信息是因为由双亲委派的机制,java.lang.String的在启动类加载器 (Bootstrap classLoader)得到加载,因为在核心jre库中有其相同名字的类文件, 但该类中并没有main方法。这样就能防止恶意篡改核心API库

4. 类装载的过程

类从加载到JVM中开始,它的整个生命周期包括了:加载、验证、准备、解析、初始化、使用和卸载七个阶段。其中,验证、准备和解析这三个部分统称为连接

加载

加载时主要的作用是以下三点:

  • 通过类的全名,获取类的二进制数据流
  • 解析类的二进制数据流为方法区内的数据结构(Java类模型)
  • 创建java.lang.Class类的实例,表示该类型。作为方法区这个类的各种数据的访问入口

上面说的可能优点难以理解,以这个图片来讲解一下它的作用。就比如当前有一个Person进行类的加载,那么他主要是分为两个部分,第一部分将Person中定义的字段以及方法存储到元空间中,第二部分时将实例化的对象存储到堆中,而堆当中的实例化对象的对象头会指向当前的class对象,然后class对象指向元空间的数据结构

验证

验证类是否符合 JVM 规范,安全性检查

  • 文件格式验证:是否符合Class文件的规范
  • 元数据验证
    • 这个类是否有父类(除了Object这个类之外,其余的类都应该有父类)
    • 这个类是否继承(extends)了被final修饰过的类(被final修饰过的类表示类不能被继承)
    • 类中的字段、方法是否与父类产生矛盾。(被final修饰过的方法或字段是不能覆盖的)
  • 字节码验证
    • 主要的目的是通过对数据流和控制流的分析,确定程序语义是合法的、符合逻 辑的
  • 符号引用验证:符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量

准备

为类变量分配内存并设置类变量初始值

  • static变量,分配空间在准备阶段完成(设置默认值),赋值在初始化阶段完成
  • static变量是final的基本类型,以及字符串常量,值已确定,赋值在准备阶段完成
  • static变量是final的引用类型,那么赋值也会在初始化阶段完成
public class Application {static int b = 10;static final int c= 20,static final String d = "hello";static final Object obj= new Object();
}

解析

把类中的符号引用转换为直接引用

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

初始化

对类的静态变量,静态代码块执行初始化操作

  • 如果初始化一个类的时候,其父类尚未初始化,则优先初始化其父类
  • 如果同时包含多个静态变量和静态代码块,则按照自上而下的顺序依次执行

使用

JVM 开始从入口方法开始执行用户的程序代码

  • 调用静态类成员信息(比如:静态字段、静态方法)
  • 使用new关键字为其创建对象实例

卸载

当用户程序代码执行完毕后,JVM 便开始销毁创建的 Class 对象,最后负责运行的 JVM 也退出内存

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 如何搭建一个圈子社区系统?开源社交陪玩交友圈子论坛帖子系统保姆级搭建教程!
  • 益九未来CEO曾宪军:创新引领,打造智能售货机行业新标杆
  • vue项目路径使用@报错
  • VS Code C/C++ MSVC编译器
  • 【React 】react 创建项目配置 jsconfig.json 的作用
  • Axure RP界面设计初探:基础操作与实用技巧
  • JavaScript青少年简明教程:异常处理
  • Java 面试常见问题之——static 的用法
  • Android 在布局中tools使用
  • Linux 调试追踪: trace-cmd 和 kernelshark
  • 16个好用到爆的Python实用脚本!
  • 如何用密码保护你的 WordPress 管理员 (wp-admin) 目录
  • 互联网之光与人工智能之光交相辉映,如何抓住5G人工智能红利
  • 为什么企业需要进行能源体系认证?
  • 8.3 字符串中等 306 Additive Number 423 Reconstruct Original Digits from English
  • Google 是如何开发 Web 框架的
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • AngularJS指令开发(1)——参数详解
  • Fastjson的基本使用方法大全
  • gcc介绍及安装
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • node-glob通配符
  • Phpstorm怎样批量删除空行?
  • 阿里云爬虫风险管理产品商业化,为云端流量保驾护航
  • 从零开始学习部署
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 观察者模式实现非直接耦合
  • 聚类分析——Kmeans
  • 聊聊hikari连接池的leakDetectionThreshold
  • 全栈开发——Linux
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 微信小程序--------语音识别(前端自己也能玩)
  • 自定义函数
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • (01)ORB-SLAM2源码无死角解析-(66) BA优化(g2o)→闭环线程:Optimizer::GlobalBundleAdjustemnt→全局优化
  • (PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测
  • (Ruby)Ubuntu12.04安装Rails环境
  • (SpringBoot)第二章:Spring创建和使用
  • (二)换源+apt-get基础配置+搜狗拼音
  • (简单) HDU 2612 Find a way,BFS。
  • (利用IDEA+Maven)定制属于自己的jar包
  • (三)Hyperledger Fabric 1.1安装部署-chaincode测试
  • (一)kafka实战——kafka源码编译启动
  • (已解决)vue+element-ui实现个人中心,仿照原神
  • .mysql secret在哪_MYSQL基本操作(上)
  • .NET C# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法的坑
  • @Autowired注解的实现原理
  • [ vulhub漏洞复现篇 ] AppWeb认证绕过漏洞(CVE-2018-8715)
  • [AIGC 大数据基础]hive浅谈
  • [BZOJ 4034][HAOI2015]T2 [树链剖分]
  • [C++]模板与STL简介
  • [codevs 1288] 埃及分数 [IDdfs 迭代加深搜索 ]
  • [COGS 622] [NOIP2011] 玛雅游戏 模拟
  • [flume$2]记录一个写自定义Flume拦截器遇到的错误
  • [GXYCTF2019]禁止套娃