【JVM原理】类加载机制

news2024/9/29 21:30:59

文章目录

  • 一、JVM组成
  • 二、类的生命周期
    • 2-1 加载 (Loading)
    • 2-2 连接 (Linking)
    • 2-3 初始化 (Initialization)
    • 2-4 使用 (Using)
    • 2-5 卸载 (Unloading)
  • 三、类加载器
    • 3-1 类加载器的作用
    • 3-2 类加载器的种类
    • 3-3 类加载机制
      • 双亲委派机制(Parent Delegation Model)
      • 全盘负责委托机制(Full Responsibility Delegation Model)

JVM (Java Virtual Machine)


一、JVM组成

JVM包括几个核心组件:

类加载器子系统:负责加载、链接和初始化类。是实现类加载机制的具体实现部分,它包括各种类加载器和它们的行为。

运行时数据区:包括堆、方法区、Java 栈、程序计数器和本地方法栈等,用于存储类、对象、方法和线程的执行状态。

执行引擎:执行字节码,包括解释器和即时编译器(JIT)。

本地接口:与本地方法库(如 C/C++)进行交互。

垃圾回收器:自动管理内存,回收不再使用的对象。

我们写的程序经过编译后成为了.class文件,.class文件中描述了类的各种信息,最终都需要加载到虚拟机之后才能运行和使用。而虚拟机如何加载这些.class文件?.class文件的信息进入到虚拟机后会发生什么变化?

二、类的生命周期

类的整个生命周期包括:加载验证准备解析初始化使用卸载这7个阶段。

在这里插入图片描述

2-1 加载 (Loading)

类加载器: 当 JVM 需要一个类时,它会通过类加载器来加载这个类。类加载器负责从文件系统、网络等地方加载类的字节码。(类的唯一性 全限定名)

类文件: 类加载器从类路径(通常是 .jar 文件或 .class 文件)中读取字节码。

转换为 Class 对象: 读取的字节码被转换为 java.lang.Class 对象,表示这个类的结构和行为。Class 对象会被存放在 JVM 的方法区(Metaspace)。

2-2 连接 (Linking)

连接阶段包括三个子阶段:

验证 (Verification): 验证字节码的合法性和安全性,确保字节码符合 Java 虚拟机规范,不会破坏 JVM 的安全性。

准备 (Preparation): 为类的静态变量分配内存,并将它们初始化为默认值(如 null0false 等)。这些变量所使用的内存都将在方法区中分配。 这一步并不包括初始化静态变量的实际值。

public static int num = 10;
public static final int num = 10;
//准备阶段赋初始值的变量指的是那些不被final修饰的static变量

解析 (Resolution): 将类中的符号引用转换为直接引用。符号引用是在编译期生成的,用于描述类、方法或字段的引用。解析过程将这些符号引用解析为实际的内存地址或引用。

2-3 初始化 (Initialization)

直到初始化阶段, Java虚拟机才真正开始执行类中编写的Java程序代码, 将主导权移交给应用程序。

  • 静态初始化块: 在这个阶段,类的静态变量会被初始化为显式的值,同时会执行类的静态初始化块(如果存在)。
  • 执行静态块: 类的静态初始化块按照在源代码中出现的顺序执行。

这一过程由编译器自动生成静态初始化方法(<clinit>()),当 Java 类被加载时,JVM 会调用 <clinit>() 方法以初始化类的静态成员。这包括静态变量的赋值和静态初始化块中的代码。

class Test {
	static class Parent {
		public static int A = 1;
		static {
			A = 2;
		}
	} 

	static class Sub extends Parent {
		public static int B = A;
	}
		
	public static void main(String[] args) {
		System.out.println(Sub.B);
	}
}
// Java虚拟机会保证在子类的()方法执行前,父类的()方法已经执行完毕。因此在Java虚拟机中第一个被执行的()方法的类型肯定是java.lang.Object

2-4 使用 (Using)

  • 实例化: 当程序需要一个类的实例时,JVM 会使用加载好的 Class 对象来创建对象。
  • 方法调用: 在程序运行过程中,通过 Class 对象调用该类的方法。

2-5 卸载 (Unloading)

  • 垃圾回收: 如果一个类的 ClassLoader 对象被垃圾回收器回收,那么该类也可能被卸载。卸载是为了释放内存,并且需要满足一定条件(例如,类的 ClassLoader 已被回收,类不再有活跃的引用)。

全限定名(Fully Qualified Name)是确定类唯一性的一种重要方法,但它并不是唯一的方法。全限定名包括包名和类名(例如 com.example.MyClass),可以唯一标识一个类。不过,如果有多个类在不同的类加载器中存在相同的全限定名,它们也可能被认为是不同的类。因此,类的唯一性还依赖于类加载器的上下文和类加载机制。

三、类加载器

3-1 类加载器的作用

层次结构管理:Java 中的类加载器以层次结构组织,确保每个类加载器都能找到其需要的类,并且保证不同加载器加载的同名类是隔离的。

3-2 类加载器的种类

jvm支持两种类型的加载器,即启动类加载器和其他类加载器,其中,启动类加载器是由c/c++实现的,其他类加载器是由java实现的。

上图中的加载器划分为包含关系而并非继承关系

启动类加载器(Bootstrap ClassLoader):加载核心 Java 类库,如 rt.jar 中的类。它是最基本的类加载器,使用c/c++实现,嵌套在jvm内部。

扩展类加载器(Platform ClassLoader/Extension ClassLoader):加载 Java 平台扩展目录中的类,通常是 jre/lib/ext 目录下的类。由 sun.misc.Launcher$ExtClassLoader 实现。

系统类加载器(Application ClassLoader):加载应用程序的类路径(classpath)中的类,是用户定义的类加载器的默认实现。由 sun.misc.Lanucher$AppClassLoader 实现。

自定义类加载器(Custom ClassLoader):开发者可以自定义实现,继承 ClassLoader 类,加载特定的类文件,满足特殊需求。例如,加载网络资源中的类文件或实现热部署功能。

在这里插入图片描述

3-3 类加载机制

双亲委派机制(Parent Delegation Model)

双亲委派机制是 Java 类加载器的主要工作模式,保证了 Java 程序的安全性和一致性。其工作流程如下:

  1. 委派
  2. 递归委派
  3. 父加载器的尝试
  4. 加载失败

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

双亲委派机制的优点

提高安全性:确保了核心类库(如 java.lang.*java.util.*)不会被用户自定义的类加载器所覆盖。所有的类加载请求都会先委派给父类加载器,如果父类加载器无法找到该类,才会由当前类加载器尝试加载。这种机制可以防止恶意代码通过自定义类加载器覆盖 Java 核心类。

减少类的重复加载:避免重复加载相同的类。减少内存中的类实例数目,并避免不同类加载器加载同一类的冲突。

在这里插入图片描述

protected Class<?> loadClass(String name, boolean resolve)
    throws ClassNotFoundException
{
    synchronized (getClassLoadingLock(name)) {
        // First, check if the class has already been loaded
        Class<?> c = findLoadedClass(name);
        if (c == null) {
            long t0 = System.nanoTime();
            try {
                if (parent != null) {
                    c = parent.loadClass(name, false);
                } else {
                    c = findBootstrapClassOrNull(name);
                }
            } catch (ClassNotFoundException e) {
                // ClassNotFoundException thrown if class not found
                // from the non-null parent class loader
            }

            if (c == null) {
                // If still not found, then invoke findClass in order
                // to find the class.
                long t1 = System.nanoTime();
                c = findClass(name);

                // this is the defining class loader; record the stats
                sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                sun.misc.PerfCounter.getFindClasses().increment();
            }
        }
        if (resolve) {
            resolveClass(c);
        }
        return c;
    }
}

从上面代码可以明显看出, loadClass(String, boolean) 函数即实现了双亲委派模型。整个大致过程如下:

首先,检查一下指定名称的类是否已经加载过,如果加载过了,就不需要再加载,直接返回。

如果此类没有加载过,那么,再判断一下是否有父加载器;如果有父加载器,则由父加载器加载(即调用 parent.loadClass(name, false); ).或者是调用 bootstrap 类加载器来加载。

如果父加载器及 bootstrap 类加载器都没有找到指定的类,那么调用当前类加载器的 findClass 方法来完成类加载。

全盘负责委托机制(Full Responsibility Delegation Model)

全盘负责委托机制(或称为"全权负责"模式)是指某个类加载器在接收到加载类的请求时,不将请求委派给父加载器,而是由该加载器自己完全负责加载过程。

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

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

相关文章

分享林曦老师的苏东坡入门阅读清单

大家暑假过得还愉快嘛假期前暄桐的课程刚好进行到六阶“见道明心的笔墨”书法部分《赤壁赋》的学习&#xff0c;也为暑假提供些新的乐趣&#xff0c;林曦老师十分贴心地送给大家一份苏东坡阅读入门清单&#xff0c;每本书有不同的侧重点。祝大家读书开心&#xff0c;有满满的收…

某张卡NR only下可以驻网 AUTO模式下在2G/3G工作

结论:需要终端设置为data centric&#xff0c;或ps only。 从日志看&#xff0c;5G下的注册收到REGISTRATION ACCEPT。但是没有携带ims support。 正常网络&#xff1a; ims_Vops_3GPP 1 (0x1) nwk_feature_supp_inc 1 (0x1)nwk_feature_supportedlength 2 (0x2)mpsi 0 (0…

JVM中篇:字节码与类的加载篇-03-类的加载过程(类的生命周期)详解

笔记来源&#xff1a;尚硅谷 JVM 全套教程&#xff0c;百万播放&#xff0c;全网巅峰&#xff08;宋红康详解 java 虚拟机&#xff09; 文章目录 1. 概述大厂面试题 2. 过程一&#xff1a;Loading&#xff08;加载&#xff09;阶段2.1. 加载完成的操作2.2. 二进制流的获取方式2…

设置文本的颜色

AndroidManifest.xml <?xml version"1.0" encoding"utf-8"?> <manifest xmlns:android"http://schemas.android.com/apk/res/android"><applicationandroid:allowBackup"true"android:icon"mipmap/ic_launcher…

如何使用查询路由构建更先进的 RAG

前言 目前大部分RAG的实践方案都是通过检索模型从外部数据库中获取与输入相关的文档或信息&#xff1b;然后&#xff0c;将这些信息与输入结合&#xff0c;输入到生成模型中进行文本生成。这种方案往往会有一个问题就是所有的数据都存储在一起&#xff0c;但这往往是没法在生产…

PCB寄生电容的影响,计算方法和消除措施

什么是PCB寄生电容&#xff1f; 寄生电容是存在于由绝缘体隔开的两个导电结构之间的虚拟电容&#xff0c;是PCB布局中的一种效应&#xff0c;其传播的信号表现为电容&#xff0c;但并不是真正意义上的电容。 寄生电容有什么影响&#xff1f; 在高速或高频电路板中&#xff0c…

Java云端联动触手可及高端台球助教教练多端系统小程序源码

&#x1f3b1;云端联动&#xff0c;触手可及&#xff01;高端台球助教教练多端系统&#xff0c;你的私人球技加速器&#x1f680; &#x1f308; 开篇&#xff1a;遇见台球新纪元 在这个科技日新月异的时代&#xff0c;台球这项优雅的运动也迎来了它的智能升级&#xff01;&am…

【机器学习】支持向量机(SVM)的基本概念、如何选择向量机(SVM)的参数以及在python中使用向量机的实例

引言 支持向量机&#xff08;SVM&#xff09;是一种在机器学习中广泛应用的二分类模型。它的核心思想是寻找一个最优的超平面&#xff0c;将不同类别的样本分隔开来。这个过程涉及到最大化间隔&#xff0c;即找到那些最接近分隔超平面的样本点&#xff0c;这些点被称为支持向量…

3秒AI写真出图,Stable Diffusion2024升级版+使用教程来了!(无需安装,解压即用

前言 要说今年摄影圈最大的新秀 那妥妥的就Stable Diffusion 比如下面的写真照片 你敢信这是SD绘画生成的&#xff1f; 本次教程将使用AI绘画工具 Stable Diffusion 进行讲解&#xff0c;如还未安装SD的小伙伴可以扫描免费获取哦~ 就在刚刚它又全面升级了 新版无需安装&a…

插入移动硬盘后【提示需要格式化】,如何修复?

遇到格式化问题&#xff0c;又想要找回数据&#xff0c;怎么办&#xff1f; 我们只需要一个数据恢复软件就能解决所有数据丢失问题 1、转转大师数据恢复 点击直达链接>>https://www.huifuzhinan.com 恢复数据类型超全面的一个软件&#xff0c;包括但不限于以下几种&…

Python开发者必备利器之Gooey使用详解

概要 在Python开发中,命令行程序是一种常见的方式来与用户交互,但有时候用户更喜欢使用图形界面来操作程序。 为了实现这一转变,我们可以使用非标准模块Gooey,它可以帮助我们将命令行程序快速转换为具有图形用户界面(GUI)的应用程序。 本文将介绍Gooey的基本概念、使用…

矩阵分析 学习笔记2 线性子空间 线性映射

子空间是啥&#xff1a; 平凡子空间&#xff1a;{0}&#xff08;只有一个0元素&#xff09;和V&#xff08;原本的子空间&#xff09; 向量组生成的子空间&#xff1a; 比如说&#xff0c;我们的三维空间就是由三个标准基组成的向量组“张”成的空间&#xff0c;而标准基组成的…

基于Pytorch框架的深度学习DeepLabv3+网络头发语义分割系统源码

第一步&#xff1a;准备数据 头发分割数据&#xff0c;总共有1050张图片&#xff0c;里面的像素值为0和1&#xff0c;所以看起来全部是黑的&#xff0c;不影响使用 第二步&#xff1a;搭建模型 DeepLabV3的网络结构如下图所示&#xff0c;主要为Encoder-Decoder结构。其中&am…

深度学习基础--模型拟合

模型拟合 损失与网络参数有关&#xff0c;本章着重于探讨如何确定能使损失最小化的参数值。这个过程称为网络参数的学习&#xff0c;或更通俗地说&#xff0c;是模型的训练或拟合。该过程首先是选取一组初始参数值&#xff0c;随后重复执行两个步骤&#xff1a; (i) 计算损失…

张驰咨询:新界泵业六西格玛设计DFSS项目出成果

近日&#xff0c;新界泵业六西格玛设计项目通过专家评审&#xff0c;新界泵业石总等领导、六西格玛设计项目组成员、张驰咨询首席顾问张驰、首席六西格设计顾问赵老师共同出席项目评审会。 &#xff08;顾问老师致辞&#xff09; 本期项目涉及多款新产品开发&#xff0c;本期…

Java新手零基础教程!Java 异常详解.^◡^.

Java 异常 Java教程 - Java异常 异常是在运行时在代码序列中出现的异常状况。例如&#xff0c;读取一个不存在的文件。 Java异常是描述异常条件的对象发生在一段代码中。 关键词 Java异常处理通过五个关键字管理: try&#xff0c;catch&#xff0c;throw&#xff0c;throws…

优思学院|质量工程师常用英语【客户投诉篇】

作为质量工程师&#xff0c;你是否曾因国外客户的投诉而不知如何用英语回应&#xff0c;感到困扰&#xff1f; 质量工程师常常面对各种挑战。即使你解决问题的能力很强&#xff0c;但由于不熟悉使用英语&#xff0c;可能会影响客户对你的印象和信任。 接下来&#xff0c;让我…

C#面试题系列--动态更新

C#面试题系列 排版排了半天&#xff0c;也是不好看&#xff0c;那就不排版了&#xff0c;尽量由易到难 高级一些 什么是MVC模式C#中特性是什么&#xff1f;如何使用&#xff1f;C#中什么是反射?C#中的委托是什么 事件是不是一种委托C# 不安全代码C# 隐式类型 varC# linqC# 匿名…

在centos中安装 --nmon性能系统监控工具

参考资料 CentOS安装nmon-CSDN博客 Jmeter(十九)&#xff1a;nmon性能系统监控工具_jmeter nmon(1)_jmeter nmon性能系统监控工具详解-CSDN博客 Linux性能监控命令_nmon 安装与使用_nmon安装方法linux-CSDN博客 资源监控工具nmon安装及使用 – TestGo 下载启宏插件 https…

学习日志8.21--防火墙NAT

在学习过基于路由器的NAT网络地址转换&#xff0c;现在学习基于防火墙NAT的网络地址转换&#xff0c;防火墙的NAT配置和路由器的NAT配置还是有比较大的区别。 防火墙NAT是通过NAT策略实现的&#xff0c;在创建防火墙NAT之前需要先创建防火墙的安全策略。防火墙是不能直接在接口…