JVM上篇之类加载子系统

news2024/11/14 4:04:38

目录

类加载子系统

内存结构

类的生命周期

类的加载过程

加载

加载class文件方式

连接

验证

验证阶段

准备

解析

初始化

类加载器

介绍

作用

分类

引导类加载器

自定义类加载器

ClassLoader

获取ClassLoader途径

双亲委派机制

介绍

执行流程

好处

打破双亲委派


类加载子系统

内存结构

Class文件

类加载子系统

运行时数据区

        方法区

        堆

        程序计数器

        虚拟机栈

        本地方法栈

执行引擎

本地方法接口

本地方法库

类的生命周期

        类从被加载到虚拟机内存中开始到卸载出内存为止,整个生命周期为7个阶段:加载、验证、准备、解析、初始化、使用、卸载;其中前三个阶段统称为连接

 卸载:jvm结束生命周期

类的加载过程

class文件需要加载到虚拟机之后才能运行和使用;主要分为三步:加载、连接、初始化;其中连接又可以分为三步:验证、准备、解析

 /**
 *示例代码
 */
public class HelloLoader {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

加载

类加载过程的第一步;

主要为了完成3件事:

        1.通过全类名获取定义此类的二进制字节流

        2.将字节流所代表的静态存储结构转换为方法区的运行时数据结构

        3.在内存中生成一个代表该类的class对象,作为方法区这些数据的访问入口

加载class文件方式

        从本地系统中直接加载

        通过网络获取

        从压缩包中获取

        运行时计算生成

        其他文件生成(jsp、html)

        从数据库中提取

        从加密文件中获取

连接

验证

主要是为了确保class文件字节流中包含的信息符合规范,保证这些信息被当作代码运行后不会危害虚拟机自身的安全。

验证阶段

准备

为类变量分配内存且设置该类变量的默认初始值。

注意

        1.进行内存分配的仅包括类变量(静态变量),而不包括实例变量

        2.这里所设置的初始值"通常情况"下是数据类型默认的零值(如 0、0L、null、false 等),比如我们定义了public static int value=111 ,那么 value 变量在准备阶段的初始值就是 0 而不是 111(初始化阶段才会赋值)。特殊情况:比如给 value 变量加上了 final 关键字public static final int value=111 ,那么准备阶段 value 的值就被赋值为 111

解析

解析是虚拟机将常量池内的符号引用替换为直接引用的过程。

解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄、调用限制符等7种符号引用进行

初始化

        初始化阶段是执行初始化方法<clinit>()方法的过程,是类加载的最后一步,之后jvm才开始执行类中定义的程序代码。

        对于<clinit>()方法的调用,jvm会确保其在多线程环境的安全性,因为<clinit>()方法是带锁线程安全,所以在多线程环境下进行类初始化可能会引起线程堵塞,并且这种堵塞很难被发现

类加载器

介绍

类加载器是一个负责加载类的对象,用于实现类加载过程中加载这一步;每个Java类都有一个引用指向加载它的ClassLoader;数组类不是ClassLoader创建的,而是jvm直接生成

作用

系统加载class类型的文件主要分为3步:加载、连接、初始化;其中连接过程又可以分为3步:验证、准备、解析

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

分类

jvm支持两种类型的加载器。分别为:引导类加载器、自定义类加载器。

自定义加载器一般指程序开发中开发人员自定义的一类类加载器,但是jvm规范却没有这么定义,而是将所有派生于ClassLoader的类加载器都划分为自定义加载器。

引导类加载器

启动类加载器(引导类加载器,Bootstrap ClassLoader)

        这个类加载使用C/C++语言实现的,嵌套在JVM内部。

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

        并不继承自ava.lang.ClassLoader,没有父加载器。

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

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

扩展类加载器(Extension ClassLoader)

        Java语言编写,由sun.misc.Launcher$ExtClassLoader实现。

        派生于ClassLoader类

        父类加载器为启动类加载器

        从java.ext.dirs系统属性所指定的目录中加载类库,或从JDK的安装目录的jre/1ib/ext子目录(扩展目录)下加载类库。如果用户创建的JAR放在此目录下,也会自动由扩展类加载器加载。

应用程序类加载器(系统类加载器,AppClassLoader)

        java语言编写,由sun.misc.LaunchersAppClassLoader实现

        派生于ClassLoader类

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

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

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

        通过ClassLoader#getSystemclassLoader() 方法可以获取到该类加载器

自定义类加载器

为什么要自定义类加载器?

        隔离加载类

        修改类加载的方式

        扩展加载源

        防止源码泄漏

实现步骤:

        1.需要继承 ClassLoader抽象类

        2.自定义的类加载逻辑写在findClass()方法中

        3.在编写自定义类加载器时,如果没有太过于复杂的需求,可以直接继承URLClassLoader类

ClassLoader

ClassLoader类是一个抽象类,其后所有的类加载器都继承自ClassLoader。

获取ClassLoader途径

1.获取当前ClassLoader

clazz.getClassLoader()

2.获取当前线程上下文的ClassLoader

Thread.currentThread().getContextClassLoader()

3.获取系统的ClassLoader

ClassLoader.getSystemClassLoader()

4.获取调用者的ClassLoader

DriverManager.getCallerClassLoader()

双亲委派机制

介绍

        当一个类收到了加载请求时,它是不会先自己去尝试加载的,而是委派给父类去完成,比如我现在要 new 一个 Person,这个 Person 是我们自定义的类,如果我们要加载它,就会先委派 App ClassLoader ,只有当父类加载器都反馈自己无法完成这个请求(也就是父类加载器都没有找到加载所需的 Class)时,子类加载器才会自行尝试加载。

        双亲委派模型并不是一种强制性的约束,只是 JDK 官方推荐的一种方式

执行流程

        1.在类加载的时候,系统会首先判断当前类是否被加载过。已经被加载的类会直接返回,否则才会尝试加载

        2.类加载器在进行类加载的时候,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成

        3.只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载(调用自己的 findClass() 方法来加载类)

protected Class<?> loadClass(String name, boolean resolve)
    throws ClassNotFoundException
{
    synchronized (getClassLoadingLock(name)) {
        //首先,检查该类是否已经加载过
        Class c = findLoadedClass(name);
        if (c == null) {
            //如果 c 为 null,则说明该类没有被加载过
            long t0 = System.nanoTime();
            try {
                if (parent != null) {
                    //当父类的加载器不为空,则通过父类的loadClass来加载该类
                    c = parent.loadClass(name, false);
                } else {
                    //当父类的加载器为空,则调用启动类加载器来加载该类
                    c = findBootstrapClassOrNull(name);
                }
            } catch (ClassNotFoundException e) {
                //非空父类的类加载器无法找到相应的类,则抛出异常
            }

            if (c == null) {
                //当父类加载器无法加载时,则调用findClass方法来加载该类
                //用户可通过覆写该方法,来自定义类加载器
                long t1 = System.nanoTime();
                c = findClass(name);

                //用于统计类加载器相关的信息
                sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                sun.misc.PerfCounter.getFindClasses().increment();
            }
        }
        if (resolve) {
            //对类进行link操作
            resolveClass(c);
        }
        return c;
    }
}

好处

        避免类的重复加载

        保护程序安全,防止核心api被篡改

打破双亲委派

        自定义加载器的话,需要继承 ClassLoader 。如果我们不想打破双亲委派模型,就重写 ClassLoader 类中的 findClass() 方法即可,无法被父类加载器加载的类最终会通过这个方法被加载。但是,如果想打破双亲委派模型则需要重写 loadClass() 方法。

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

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

相关文章

01-RocketMQ整体理解与快速实战

上一篇&#xff1a;RocketMQ从入门到精通汇总 一、MQ介绍 1、什么是MQ&#xff1f;为什么要用MQ&#xff1f; MQ&#xff1a;MessageQueue&#xff0c;消息队列。 队列&#xff0c;是一种FIFO 先进先出的数据结构。消息由生产者发送到MQ进行排队&#xff0c;然后按原来的顺序…

解决 Centos 安装 Python 3.10 的报错: Could not import runpy module

操作环境&#xff1a;CentOS 7、Gcc 4.8.5、Python 3.10.0 系统上已经有 2.x&#xff0c;3.6 版本的 Python 了&#xff0c;但是还是想装一个 3.10 的。因为刚写的脚本文件是较高版本的&#xff0c;在 3.6 上无法正常运行&#xff0c;Python 语法不是很了解&#xff0c;只能从…

[每周一更]-(第66期):Docker 守护进程说明

Docker 的优势 Build once, Run anywhere 上面这句话很精辟的总结了 docker 的优点。我从下面几点具体描述 docker 带给开发者的能力 应用标准化 无论什么语言开发的应用&#xff0c;我们都能用 dockerfile 和构建脚本方便的进行应用构建打包&#xff0c;代码库 构建 regis…

华为交换机vlan划分、telnet 管理地址配置

------1--- 1台核心交换时s5700 2台汇聚交换机S3700 6台PC -----2------ 创建vlan 10 20 30 s3700下PC1,PC2,PC3 S3700下PC4,PC5,PC6 VLAN10 PC1,PC2 VLAN20 PC3,PC4 VLAN30 PC5,PC6 -------3----- 要求实现&#xff1a; PC1,PC2互通&#xff1b; PC3,PC4互通&#xff1b; P…

【吞噬星空4】徐欣因祸得福,罗峰强势复仇,两大强者被杀,阿特金已开始自救

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析吞噬星空国漫。 吞噬星空第89集预告已经出来了&#xff0c;从预告来看&#xff0c;信息量是真的多。从徐欣因祸得福到罗峰强势复仇&#xff0c;再到两大强者被杀&#xff0c;乃至于最后的阿特金已开始自救。那么多的不说&…

3分钟轻松实现网关网口远程监控安川PLC

EG网关网口连接安川PLC 目录 EG网关网口连接安川PLC 一. 准备工作 1.1 在对接前我们需准备如下物品 1.2 EG20网关准备工作 1.3 PLC准备工作 1.4 添加MEMOBUS协议 二. EMCP平台设置 2.1 新增EG设备 2.2 远程配置网关 2.3 网关绑定 2.4 通讯参数设置 2.5 创建设备驱动…

以单颗CMOS摄像头重构三维场景,维悟光子发布单目红外3D成像模组

维悟光子近期发布全新单目红外3D成像模组,现可提供下游用户进行测试导入。通过结合微纳光学元件编码和人工智能算法解码,维悟光子单目红外3D成像模组采用单颗摄像头,通过单帧拍摄,可同时获取像素级配准的3D点云和红外图像信息,可被应用于机器人、生物识别等广阔领域。 市场…

vxe是一款功能强大的table,有vue2/3版本

vxe-table v4https://vxetable.cn/#/table/start/install 当计算上千&#xff0c;上万条数据的和&#xff0c;或者算数平方根时可以使用web worker&#xff0c;来实现复杂&#xff0c;大量的计算&#xff0c;同时也不会造成浏览器的卡顿&#xff0c;暂时只是知道&#xff0c;还…

rxjava2源码分析

目录 一&#xff0c;Observable调用流程 1.1 简单Observable.create()创建调用流程 1.2 map操作符 1.3 flatmap操作符 1.4 subscribeOn操作符 1.5 observeOn操作符 一&#xff0c;Observable调用流程 1.1 简单Observable.create()创建调用流程 上面的这个流程图是下面这…

河北吉力宝搭建中国鞋业全产业链生态流通体系

中国鞋业&#xff0c;一直以来都是劳动密集型产业的代表&#xff0c;传统的制造和销售方式已经不能满足当今市场的需求。在这个充满机遇和挑战的时代&#xff0c;河北吉力宝旗下的品牌步力宝&#xff0c;以鞋为媒介&#xff0c;积极参与商业创新&#xff0c;正引领中国鞋业向前…

idea提交git项目,提交代码 点击commit一闪而过,没有反应的解决办法

idea提交git项目&#xff0c;提交代码 点击commit一闪而过&#xff0c;没有反应的解决办法 一般有两种情况导致一闪而过&#xff0c;一种为git设置问题&#xff0c;一种是编码问题&#xff0c;解决方案如下&#xff1a; 1、在单文件提交时不会遇到这种情况&#xff0c;但是在…

Java架构师缓存通用设计方案

目录 1 采用多级缓存2 缓存数据尽量前移3 静态化4 数据平衡策略5 jvm缓存的问题6 redis存放数据解决7 redis垂直拆分8 总结1 采用多级缓存 对于高性能的缓存设计呢,咱们前面按照专题详细去进行的讲解。那咱们现在结合着咱们实际的应用呢,再来确定一下咱们怎么去做这个高性能的…

colab切换目录的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

【java|golang】多字段排序以及排序规则

奖励最顶尖的 K 名学生 给你两个字符串数组 positive_feedback 和 negative_feedback &#xff0c;分别包含表示正面的和负面的词汇。不会 有单词同时是正面的和负面的。 一开始&#xff0c;每位学生分数为 0 。每个正面的单词会给学生的分数 加 3 分&#xff0c;每个负面的词…

品牌低价的形式有哪些

线上产品五花八门&#xff0c;价格也有高低&#xff0c;但有时同一款商品&#xff0c;看似页面价一样&#xff0c;计算完促销信息后的到手价都会有所不同&#xff0c;有些店铺甚至会使用隐藏优惠券&#xff0c;如咨询客服领券、新人券等&#xff0c;而这些丰富的优惠方式&#…

华为OD机试 - 最大括号深度 - 栈stack(Java 2023 B卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#…

深入剖析 | 近期法院判决是不是司法部门有意平衡 SEC 监管天平

出品 &#xff5c;欧科云链研 究院 作者&#xff5c;Matthew Lee 9月27日&#xff0c;SEC 主席 Gary Gensler 参加了美国众议院金融服务委员会听证会。听证会审查 SEC 自 2021 年 10 月 5 日以来的一段时间内的监管发展、规则制定和活动&#xff0c;其中包括 SEC 提议修改“交易…

python图片:获得颜色占比,图片尺寸

꧂ 获得颜色占比&#xff0c;图片尺寸꧁ 要获取图片的尺寸、大小和颜色占比大于0.001的颜色值&#xff0c;可以基于上一个回答中使用Pillow库的代码进行修改。 from PIL import Image# 输入图片路径 image_path input("请输入图片路径: ")try:# 打开图片文件image …

零售超市商家怎么做微信小程序

随着互联网的发展&#xff0c;越来越多的零售超市商家开始关注如何借助微信小程序引流&#xff0c;以提高销售额和客户满意度。下面将介绍几个策略&#xff0c;帮助零售超市商家借助微信小程序实现引流。 首先&#xff0c;商家需要开发一款适合自己的微信小程序。小程序是一种轻…

win11右键菜单显示更多的设置方法

用了一年多win11系统了&#xff0c;Win11最大的变化之一莫过于右键菜单发生了变化。右键菜单很多时候需要点两次&#xff0c;实在是反人类&#xff0c;太麻烦了。 必须使用“显示更多选项”的右键菜单。 今天分享一个使用命令行更改右键菜单显示更多的设置方法&#xff1a; …