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

JVM类的加载和类的加载器

JVM类的加载和类的加载器

一.类的加载过程

类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。
在这里插入图片描述

1.加载

一般来说加载分为以下几步:

  1. 通过一个类的全限定名获取此类的二进制字节流
  2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
  3. 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口
加载.class文件的方式
  • 从本地系统中直接加载

  • 通过网络获取,典型场景: web Applet

  • 从zip压缩包中读取,成为口后jar、war格式的基础

  • 运行时计算生成,使用最多的是:动态代理技术由其他文件生成,典型场景: JSP应用

  • 从专有数据库中提取.class文件,比较少见

  • 从加密文件中获取,典型的防class文件被反编译的保护措施

2.链接

2.1验证(Verify)
  • 目的在于确保class文件的字节流中包含信息符合当前虚拟机要求,保证被加载类的正确性,不会危害虚拟机自身安全。
  • 主要包括四种验证,文件格式验证,元数据验证,字节码验证,符号引用验证
2.2准备(Prepare)
  • 为类变量分配内存并且设置该类变量的默认初始值,即零值。

  • 这里不包含用final修饰的static,因为fina1在编译的时候就会分配了,准备阶段会显式初始化;

  • 这里不会为实例变量分配初始化,类变量会分配在方法区中,而实例变量是会随着对象一起分配到Java堆中

2.3解折(Resolve)
  • 将常量池内的符号引用转换为直接引用的过程。

  • 解析操作往往会伴随着JVM在执行完初始化之后再执行。

  • 符号引用就是一组符号来描述所引用的目标。符号引用的字面量形式明确定义在《java虚拟机规范》的class文件格式中。直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄。

  • 解析动作主要针对类或接口、字段、类方法、接口方法、方法类型等。对应常量池中的CONSTANT class info、CONSTANT Fieldref info、CONSTANT Methodref info等

3.初始化

  • 初始化阶段就是执行类构造器方法clinit的过程。

  • 此方法不需定义,是javac编译器自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并而来。

  • 构造器方法中指令按语句在源文件中出现的顺序执行。

  • clinit()不同于类的构造器。(关联: 构造器是虚拟机视角下的clinit

  • 若该类具有父类,JM会保证子类的clinit() 执行前,父类的clinit(已经执行完毕。

  • 虚拟机必须保证一个类的clinit方法在多线程下被同步加锁
    在这里插入图片描述

二.类的加载器

4.作用

  • 类加载器子系统负责从文件系统或者网络中加载class文件,class文件在文件开头有特定的文件标识。

  • classLoader只负责class文件的加载,至于它是否可以运行,则由ExecutionEngine决定。

  • 加载的类信息存放于一块称为方法区的内存空间。除了类的信息外,方法区中还会存放运行时常量池信息,可能还包括字符串字面量和数字常量(这部分常量信息是class文件中常量池部分的内存映射)

在这里插入图片描述

5.分类

  • JVM支持两种类型的类加载器,分别为引导类加载器 (BootstrapclassLoader)和自定义类加载器[user-Defined ClassLoader)
  • 从概念上来讲,自定义类加载器一般指的是程序中由开发人员自定义的一类类加载器,但是Java虚拟机规范却没有这么定义,而是将所有派生于抽象classLoader的类加载器都划分为自定义类加载器。
  • 无论类加载器的类型如何划分,在程序中我们最常见的类加载器始终只有3个,如下所示:

在这里插入图片描述

这里的四者之间的关系是包含关系。不是上层下层,也不是子父类的继承关系。

5.1启动类加载器(引导类加载器,Bootstrap ClassLoader)
  • 这个类加载使用C/C++语言实现的,嵌套在JVM内部。

  • 它用来加载Java的核心库 (JAVA HOME/re/lib/rt.jar、resources.jar或sun.boot.class.path路径下的内容),用于提供JVM自身需要的类

  • 并不继承自java.lang.classLoader,没有父加载器

  • 加载扩展类和应用程序类加载器,并指定为他们的父类加载器

  • 出于安全考虑,Bootstrap启动类加载器只加载包名为java、javax、sun等开头的类

5.2扩展类加载器(Extension ClassLoader)
  • Java语言编写,由sun.misc.LauncherSExtClassLoader实现
  • 派生于classLoader类
  • 父类加载器为启动类加载器
  • 从java.ext.dirs系统属性所指定的目录中加载类库,或从JDK的安装目录的ire/lib/ext子目录(扩展目录)下加载类库。如果用户创建的JAR放在此目录下,也会自动由扩展类加载器加载。
5.3应用程序类加载器(系统类加载,AppclassLoader)
  • java语言编写,由sun.misc.LauncherSAppClassLoader实现

  • 派生于classLoader类

  • 父类加载器为扩展类加载器

  • 它负责加载环境变量classpath或系统属性 java.class.path 指定路径下的类库

  • 该类加载是程序中默认的类加载器,一般来说,Java应用的类都是由它来完成加载

  • 通过classLoader.getSystemClassLoader0)方法可以获取到该类加载器

5.4用户自定义类加载器

在Java的日常应用程序开发中,类的加载几乎是由上述3种类加载器相互配合执行的,在必要时,我们还可以自定义类加载器,来定制类的加载方
为什么要自定义类加载器?

  • 隔离加载类
  • 修改类加载的方式
  • 扩展加载源
  • 防止源码泄漏

用户自定义类加载器实现步骤:

1.开发人员可以通过继承抽象类java.lang.classLoader类的方式,实现自己的类加载器,以满足一些特殊的需求

2.在JDK1.2之前,在自定义类加载器时,总会去继承classLoader类并重写loadclass0)方法,从而实现自定义的类加载类,但是在JDK1.2之后已不再建议用户去覆盖loadclass()方法,而是建议把自定义的类加载逻辑写在findclass()方法中

3.在编写自定义类加载器时,如果没有太过于复杂的需求,可以直接继承URIClassLoader类,这样就可以避免自己去编写findclass()方法及其获取字节码流的方式,使自定义类加载器编写更加简洁。

classLoader类,它是一个抽象类,其后所有的类加载器都继承自classLoader (不包括启动类加载器)

在这里插入图片描述

获取ClassLoader的途径

  • 方式一:获取当前类的ClassLoader
    clazz.getClassLoader()
  • 方式二:获取当前线程上下文的ClassLoader
    Thread.currentThread().getContextClassLoader()
  • 方式三:获取系统的ClassLoader
    ClassLoader.getSystemClassLoader()
  • 方式四:获取调用者的ClassLoader
    DriverManager.getCallerClassLoader

相关文章:

JVM类的加载和类的加载器

JVM类的加载和类的加载器 一.类的加载过程 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于…...

MLM:多模态大型语言模型的简介、微调方法、发展历史及其代表性模型、案例应用之详细攻略

MLM:多模态大型语言模型的简介、微调方法、发展历史及其代表性模型、案例应用之详细攻略 目录 相关文章 AI之MLM:《MM-LLMs: Recent Advances in MultiModal Large Language Models多模态大语言模型的最新进展》翻译与解读 MLM之CLIP:CLIP…...

Java健康养老智慧相伴养老护理小程序系统源码代办陪诊陪护更安心

健康养老,智慧相伴 —— 养老护理小程序,代办陪诊陪护更安心 🌈【开篇:智慧养老,新时代的温馨守护】🌈 在这个快节奏的时代,我们总希望能给予家人更多的关爱与陪伴,尤其是家中的长…...

Python | Leetcode Python题解之第390题消除游戏

题目&#xff1a; 题解&#xff1a; class Solution:def lastRemaining(self, n: int) -> int:a1 1k, cnt, step 0, n, 1while cnt > 1:if k % 2 0: # 正向a1 stepelse: # 反向if cnt % 2:a1 stepk 1cnt >> 1step << 1return a1...

Github 2024-09-01 开源项目月报 Top16

根据Github Trendings的统计,本月(2024-09-01统计)共有16个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目9TypeScript项目5Dart项目2C项目1Jupyter Notebook项目1Rust项目1开发者职业成长指南 创建周期:2670 天开发语言:TypeScript协议类…...

C++ 继承(二)

目录 1. 实现一个不能被继承的类 2. 友元与继承 3.继承与静态成员 4.多继承及其菱形继承问题 (1). 继承模型 (2). 虚继承 (2.1)虚继承解决数据冗余和二义性的原理 (3). 多继承中指针偏移问题 (4). IO库中的菱形虚拟继承 5. 继承和组合 1. 实现一个不能被继承的类 方法1…...

第 2 章:AJAX 的使用

AJAX 的使用 核心对象&#xff1a;XMLHttpRequest&#xff0c;AJAX 的所有操作都是通过该对象进行的。 1. 使用步骤 创建 XMLHttpRequest 对象 var xhr new XMLHttpRequest(); 设置请求信息 xhr.open(method, url);//可以设置请求头&#xff0c;一般不设置 xhr.setReques…...

ROS——视觉抓取

纲要 视觉抓取中的关键技术 内参标定 物体识别定位 抓取姿态分析 运动规划 外参标定 任意两个位姿之间的关系 眼在外 眼在内 手眼标定流程 robot 部分 标定效果 视觉抓取例程 grasping_demo.cpp 获取两个坐标系之间变换关系:waitForTransform 、 LookupTransform 求相…...

EPLAN2022基础教程

EPLAN2022软件介绍 EPLAN是一款专业的电气设计和绘图软件&#xff0c;它可以帮助我创建和管理电气项目&#xff0c;生成各种报表和文档&#xff0c;与其他软件和系统进行交互&#xff0c;优化工程流程和质量。与传统的CAD绘图对比&#xff0c;EPLAN更适合绘制电气原理图。 下…...

【JavaWeb】Servlet 详解(处理逻辑及常见方法)

文章目录 1. Tomcat1.1 常见的错误1.1.1 出现 4041.1.2 出现 4051.1.3 出现 500 1.2 HttpServlet1.2.1 Tomcat 的处理逻辑1.2.2 相关方法 1.3 HttpServletRequest1.3.1 常见方法1.3.2 jackson 处理逻辑 1.4 HttpServletResponse1.4.1 常见方法 1. Tomcat tomcat 是一个 HTTP 服…...

6 自研rgbd相机基于rk3566之深度计算库程序详解

自研rgbd相机基于rk3566之深度计算库详解 1 tof深度计算库框架读入深度图像参数配置tof模组标定参数读入及解析深度计算函数接口2 tof深度计算库程序详解深度计算程序头文件深度计算程序 源文件1 tof深度计算库框架 读入深度图像参数配置 支持raw8/raw10/raw16 格式 /*******…...

分布式系统框架hadoop3入门

分布式系统框架hadoop3入门 (qq.com) Hadoop3作为分布式系统架构的重要基石&#xff0c;为大规模数据存储与处理提供了强大支持 基本信息 hadoop&#xff1a;一个存储和处理大数据的分布式系统框架 组成&#xff1a; HDFS&#xff08;数据存储&#xff09;、MapReduce&…...

使用 i3.LayoutCell() 方法绘制版图并输出为 GDS 文件

使用 i3.LayoutCell 方法绘制版图并输出为 GDS 文件 引言正文引言 在 IPKISS i3.SRef() 函数 一文中我们介绍了如何使用 i3.SRef() 函数将 instance 对象添加到 i3.LayoutCell() 创建的 Cell 对象上。但是当我们使用 write_gdsii() 输出版图时代码就会报错。这里我们将介绍如何…...

mariadb容器

下载镜像 $ sudo docker pull mariadb启动容器 $ sudo docker run --name my-mariadb -d -e MARIADB_DATABASEtestdb -e MARIADB_ROOT_PASSWORDLetmein -p 3306:3306 mariadb上面命令会启动一个名为my-mariadb的容器&#xff0c;并初始化一个testdb数据库&#xff0c;同时设置…...

应用层协议Http

Http协议 1.1 什么是http协议 在进行网络通信时&#xff0c;应用层协议一般都是程序员自己写的&#xff0c;但是有一些大佬其实已经定义出了一些现成的应用层协议&#xff0c;例如&#xff1a;HTTP&#xff08;超文本传输协议&#xff09;、FTP&#xff08;文件传输协议&#…...

display flex 的div 被子元素撑开不显示滚动条的一个解决demo

display flex 的div 被子元素撑开&#xff0c;不显示y轴滚动条的 一个解决demo。 注&#xff1a; 不一定适用所有人的的相同问题 less # less .contact {display: flex;flex-grow: 1;overflow: hidden auto;flex-direction: column;.contact-items {flex: 1 1 0;display: flex…...

判断键盘输入是数字、大写字母还是小写字母——C#学习笔记

以下代码将判断键盘输入字符是数字 还是字母&#xff1a; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace ConsoleApp4 {using System;using System.Threading;public class BoolKeyTest{sta…...

进程控制块PCB的组织方式有哪些?

进程控制块&#xff08;PCB&#xff0c;Process Control Block&#xff09;是操作系统用来管理和跟踪进程的一个数据结构&#xff0c;它保存了与进程相关的各种信息。PCB 是操作系统调度进程的核心数据结构&#xff0c;通常通过某种组织方式进行管理。常见的 PCB 组织方式主要有…...

getent passwd 获取linux并显示用户账户信息

getent passwd 命令在Unix和类Unix系统&#xff08;如Linux&#xff09;中用于从系统的密码数据库&#xff08;通常是/etc/passwd文件&#xff0c;但在某些配置中可能是通过网络服务如NIS或LDAP&#xff09;中获取并显示用户账户信息。这个命令的输出列出了系统上所有用户的详细…...

达梦数据库+JPA+Springboot 报错 :无效的列名

文章目录 0、 开发环境1、需求说明2、适配过程3、问题描述和解决3.1报错问题3.2 问题解决 0、 开发环境 开发环境&#xff1a; idea 2022 SpringBoot版本 &#xff1a;2.7.1 JDK 111、需求说明 适配国产化数据库达梦8 2、适配过程 参考 Springboot jpa 达梦 3、问题描述…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...