JVM-类加载机制

名词解释
*.class文件的结构
查看指令: javap -verbose hello.class
包含信息:

结构信息(版本号,大小信息);

元数据(类,继承,接口,字段声明,方法声明);

方法信息(语句,表达式,异常,堆栈大小与类型,调试信息)

符号引用
符号引用符号引用就是 class 文件中的     
1. CONSTANT_Class_info 
2. CONSTANT_Field_info
3. CONSTANT_Method_info等类型的常量
符号引用以 一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能够无歧义的定位到目标即可,使用符号引用时,被引用的目标不一定已经加载到内存中。
直接引用
直接引用可以是指向目标的指针,相对偏移量或是一个能间接 定位到目标的句柄
如果有 了直接引用,那引用的目标必定已经在内存中存在

参考:

个人理解,如果使用符号引用,虚拟机其实也不知道具体引用的类的内存地址,那么也就无法真正的调用到该类,所以要把符号引用转为直接引用,这样就能够真正定位到类在内存中的地址,如果符号引用转直接引用失败,就说明类还没有被加载到内存中,就会报错。

https://blog.csdn.net/weixin_38106322/article/details/109239971

类加载机制概述

1、类加载器把编译好的那些“.class”字节码文件给加载到JVM中,供后续代码运行来使用。
2、JVM基于自己的 字节码执行引擎,来执行加载到内存里的类。
3、类加载的时机
一个类被使用到到时候
eg:比如你的代码中有一个“main()”方法,那么JVM就会从这个“main()”方法开始执行里面的代码。他需要哪个类的时候,就会使用类加载器来加载对应的类,反正对应的类就在“.class”文件中。
4、通过Java命令执行代码的大体流程如下:
java  xxx 指令 在Windows下对应就是一个exe文件。dll 相当于java jar包。
C++启动程序 -》创建java虚拟机 -》java类加载器 -》加载class文件

类加载机制详解

类是如何加载到jvm中
JVM 类加载机制分为五个部分:加载,验证,准备,解析,初始化,下面我们就分别来看一下这五个过程。

加载过程分析

1. 加载

通过类全名来获取定义此类的二进制字节流,
将字节流所代表的 静态存储结构转换为方法区中运行时数据结构
在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
扩展:
  • 静态存储结构:数据存储于class文件的结构。
  • 运行时数据结构:数据存储于JVM的数据结构。
  • 二进制流是从.class文件中获取的。这个class文件并不一定只来源于本地,也可以来源于网络等。

2. 连接

将java二进制代码合并到java运行状态中的过程。
  • 验证:校验字节码文件的正确性 目的保证class流的格式正确。
(简单来说,这一步就是根据Java虚拟机规范,来校验你加载进来的“.class”文件中的内容,是否符合指定的规范。)
  • 准备:Java虚拟机为类变量(static修饰的变量)、加载到内存中的类分配内存空间,设置默认初始值。
    •   示例代码:
public static int v=1; 在准备阶段中,v会被设置为0   在初始化的<clinit>中才会被设置为1
对于static final类型,在准备阶段就会被赋上正确的值: public static final  int v=1;
  • 解析::将符号引用替换为直接引用
    • 该阶段会把一些静态方法(符号引用,比如 main()方法)替换为指向数据所存内存的指针或句柄等(直接引用),这是所谓的静态链接过 程(类加载期间完成),
    • 动态链接:是在程序运行期间完成的将符号引用替换为直接引用
3  初始化 (核心阶段)
初始化阶段是类加载最后一个阶段,前面的类加载阶段之后,除了在加载阶段可以自定义类加载器以外,其它操作都由 JVM 主导。到了初始阶段,才开始真正执行类中定义的 Java 程序代码。如: 在初始化阶段,JVM执行类的初始化语句, 为类的静态变量赋予用户给定的初始值,执行静态代码块 
什么时候会初始化一个类?
一般来说有以下一些时机:比如“new ReplicaManager()”来实例化类的对象了,此时就会触发类的加载到初始化的全过程,把这个类准备好,然后再实例化一个对象出来;(这里也说明了为什么 构造方法是在 静态代码块之后执行(先准备代码在实例化 ))
或者是包含“main()”方法的主类,必须是立马初始化的。
此外,这里还有一个非常重要的规则,就是如果初始化一个类的时候,发现他的父类还没初始化,那么必须先初始化他的父类

4 使用

5 卸载

http://www.cnblogs.com/ITtangtang/p/3978102.html

加载器的类型

类加载器类型总体来说可以分为以下几种:启动类加载器、其他类加载器。类的加载过程遵循双亲委派模型。
1、Bootstrap ClassLoader(启动类加载器)
JVM启动,启动类加载器 加载 Java安装目录下jre 的 “lib”目录中的核心类库
/opt/apps/jdk1.8.0_251/jre/lib
--> rt.jar、charsets.jar等> rt.jar、charsets.jar等
2、Extension ClassLoader(扩展类加载器)
JVM启动,通过扩展类加载器加载“lib/ext”目录
[root@iZ2zei4wx78lgr80odfj6eZ ext]# pwd# pwd
/opt/apps/jdk1.8.0_251/jre/lib/ext
3、Application ClassLoader(应用程序类加载器)
加载ClassPath 环境变量所指定的路径中的类
4、自定义类加载器    
根据自己需求进行类加载

类加载器初始化过程

参见类运行加载全过程图可知其中会创建JVM启动器实例sun.misc.Launcher。 
sun.misc.Launcher初始化使用了单例模式设计,保证一个JVM虚拟机内只有一个 sun.misc.Launcher实例。 
在Launcher构造方法内部,其创建了两个类加载器,分别是 sun.misc.Launcher.ExtClassLoader(扩展类加载器)和sun.misc.Launcher.AppClassLoader(应 用类加载器)。 
JVM默认使用Launcher的getClassLoader()方法返回的类加载器AppClassLoader的实例加载我们 的应用程序。

双亲委派模型

概述(向上寻找、向下委托)

类加载器收到类加载的请求,它首先不会自己去尝试加载这个类,而是 把这个请求委派给父类加载器完成。
每个类加载器都是如此,只有当父加载器在自己的搜索范围内找不到指定的类时(即ClassNotFoundException),
子加载器才会尝试自己去加载,这个过程为称为双亲委派模型。

AppClassLoader加载类的双亲委派机制源码

AppClassLoader 的loadClass方法最终会调用其父类ClassLoader的loadClass方法,
  • 1. 首先,检查一下指定名称的类是否已经加载过,如果加载过了,就不需要再加载,直接 返回。 
  • 2. 如果此类没有加载过,那么,再判断一下是否有父加载器;如果有父加载器,则由父加 载器加载(即调用parent.loadClass(name, false);).或者是调用bootstrap类加载器来加 载。
  • 3. 如果父加载器及bootstrap类加载器都没有找到指定的类,那么调用当前类加载器的 findClass方法来完成类加载。 
  • 对应代码位置://ClassLoader的loadClass方法,里面实现了双亲委派机制

为什么需要双亲委派模型

  • 保证类加载机制的安全性。
    • 防止病毒代码植入,自己写的java.lang.String.class类不会被加载,这样便可以防止核心 API库被随意篡改
  • 避免类的重复加载:
    • 当父亲已经加载了该类时,就没有必要子ClassLoader再加载一 次,保证被加载类的唯一性
  • 参考 : https://www.cnblogs.com/wxd0108/p/6681618.html

全盘负责委托机制 

  • “全盘负责”是指当一个ClassLoder装载一个类时,除非显示的使用另外一个ClassLoder,该类 所依赖及引用的类也由这个ClassLoder载入。

如何打破双亲委派模式

  • 覆写loadClass方法
    •  protected Class<?> loadClass(String name, boolean resolve)
    • 执行findClass()
      • 首先会使用自定义类加载器加载类, 不在向上委托, 直接由自己执行
    • 参考:https://www.cnblogs.com/ITPower/p/13211490.html

打破双亲委派模式的案例

  • tomcat类加载器
    • Common类加载器,加载Tomcat和Web应用都复用的类。
    • Catalina类加载器,加载Tomcat专有类(这些类在web应用中不可见)
    • Shared类加载器,加载所有Web应用都复用都类。(这些类tomcat中不可见)
    • WebappClassLoader:webapp私有的类加载器,只对当前webapp可见
  • Jsp类加载器,不同的jsp页面有不同的类加载器,方便实现jsp页面的热插拔。
  • 类加载机制原理
    • a. CommonClassLoader能加载的类都可以被Catalina ClassLoader和SharedClassLoader使用,从而实现了公有类库的共用

      b. CatalinaClassLoader和Shared ClassLoader自己能加载的类则与对方相互隔离

      c. WebAppClassLoader可以使用SharedClassLoader加载到的类,但各个WebAppClassLoader实例之间相互隔离,多个WebAppClassLoader是同级关系

      d. 而JasperLoader的加载范围仅仅是这个JSP文件所编译出来的那一个.Class文件,它出现的目的就是为了被丢弃:当Web容器检测到JSP文件被修改时,会替换掉目前的JasperLoader的实例,并通过再建立一个新的Jsp类加载器来实现JSP文件的HotSwap功能

  • 为什么打破双亲委派模式?
    • 隔离性
      • 一个web应用可以部署多个应用程序,不同的应用程序可能会依赖同一个第三方类库的不同版本。
        • 因此需要保证每个应用程序的类库是独立的、相互隔离的。
      • web容器也有自己的类库,不能和应用程序的类库混淆,需要相互隔离
    • 共享性
      • 部署在同一个web容器中的相同类库的相同版本可以共享,否则,会有重复的类库被加载进JVM
    • 独立性
      • web容器支持jsp文件修改后不用重启,jsp文件也是要编译成.class文件的,支持HotSwap功能
  • tomcat如何打破双亲委派模式的?
    • 参考tomcat类加载机制 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

应用监控 eBPF 版:实现 Golang 微服务的无侵入应用监控

作者&#xff1a;古琦 在现代软件架构中&#xff0c;微服务已成为构建可扩展和灵活应用程序的流行方式。每个微服务负责应用程序的一部分功能&#xff0c;它们共同工作以提供完整的服务。由于微服务架构的分散特性&#xff0c;监控变得至关重要&#xff0c;有效的微服务监控是…

视频推拉流EasyDSS平台直播通道重连无法转推的原因排查与解决

视频推拉流EasyDSS视频直播点播平台&#xff0c;集视频直播、点播、转码、管理、录像、检索、时移回看等功能于一体&#xff0c;可提供音视频采集、视频推拉流、播放H.265编码视频、存储、分发等视频能力服务。 用户使用EasyDSS平台对直播通道进行转推&#xff0c;发现只要关闭…

Object.keys()的用法

1、语法 Object.keys(obj) 参数&#xff1a;要返回其枚举自身属性的对象 返回值&#xff1a;一个表示给定对象的所有可枚举属性的字符串数组 2、处理对象&#xff0c;返回可枚举的属性数组 let person {name:“张三”,age:25,address:“深圳”,getName:function(){}} Obj…

Wireshark——获取指定协议的数据包

1、问题 使用Wireshark捕获了大量的数据包&#xff0c;但是只想要指定协议的数据包。 2、方法 例如&#xff0c;只想要Modbus/TCP协议的数据包。 在应用显示过滤器中输入协议的名称&#xff08;小写&#xff09;&#xff0c;回车。 选择文件&#xff0c;导出特定分组。 将所…

基于redis实现用户登陆

因为session有数据共享问题&#xff0c;不同tomcat服务器中的session不能共享&#xff0c;之后负载均衡就无法实现。所以我们用redis代替session。redis可以被多个tomcat服务器共享&#xff0c;redis基于内存。 之前的session可以看做登陆凭证&#xff0c;本次登陆凭证由sessi…

算法 - 【受限条件下可到达节点的数目】

受限条件下可到达节点的数目 题目示例1示例2 分析代码 题目 现有一棵由 n 个节点组成的无向树&#xff0c;节点编号从 0 到 n - 1 &#xff0c;共有 n - 1 条边。给你一个二维整数数组 edges &#xff0c;长度为 n - 1 &#xff0c;其中 edges[i] [ai, bi] 表示树中节点 ai 和…

python基础第二天

世界杯小组赛成绩 注意&#xff1a; 1.循环 1.1while 1.2for 1.3 range 1.4 while else while 循环正常执行完才能执行else语句

数据库(mysql)-新手笔记-基本知识点(1)

基本概念 数据库 Database :存储数据的容器 表 Table : 在数据库中存储的基本结构,它由行和列组成 行 Row : 表中的一条记录 列 Column : 表中的字段,定义了数据的类型和约束 数据类型 数据值 如 INT(整型),FLAOT(浮点型) ,DECIMAL (精确小数点) 字符串 如 VARCHAR(可变长度字…

探索AI视频创新:Sora的奇迹

探索AI视频创新&#xff1a;Sora的奇迹 随着科技的不断演进&#xff0c;AI视频模型已经成为人工智能领域的一颗新星。在这场技术的风暴中&#xff0c;OpenAI的Sora模型以其杰出的性能和前瞻性的技术脱颖而出&#xff0c;正引领着AI视频领域的全新创新浪潮。 Sora的技术之光 …

【JS】关于this的使用

this 前言一、this是什么&#xff1f;二、做什么&#xff1f;1.全局环境2.函数环境3.new实例对象4.apply、bind、call绑定4.1 apply()4.2 call()4.3 bind() 三、为什么用this&#xff1f;四、如何改变this&#xff1f;五、应用场景&#xff1f;总结 前言 痛点 经常写Vue项目&a…

(3)(3.3) MAVLink高延迟协议

文章目录 前言 1 配置 2 说明 3 消息说明 前言 ArduPilot 支持 MAVLink 高延迟协议(MAVLink High Latency)。该协议专为卫星或 LoRA 等低带宽或高成本链路而设计。 在此协议中&#xff0c;每 5s 只发送一次 HIGH_LATENCY2 MAVLink 信息。对 MAVLink 命令或请求&#xff08…

使用 Grafana 使用JSON API 请求本地接口 报错 bad gateway(502)解决

一 . 问题&#xff1a; 在用docker部署Grafana 来实现仪表盘的展示&#xff0c;使用到比较多的就是使用JAON API插件调用本地部署的API&#xff0c;比如访问localhost下的 /test_data 接口&#xff0c;一般我们使用的是http://localhost:8080/test_data&#xff0c; 但是在访…