学习总结与分享-ClassLoader类加载器与类加载机制

Java ClassNotFoundException 根因解析类加载器排错指南 ClassNotFoundException 是 Java 运行时最常见却最易误判的异常,本质并非‘不存在’,而是 JVM 类加载机制路径(Classpath)或模块路径(Module Path)中未能定位目标。其底层原理根植于双亲委派模型——Bootstrap、Extension 和 Application 三层类加载器协同工作,严格遵循委托优先、隔离加载的原则。该异常的技术价值在于暴露环境配置缺陷而非代码错误,是诊断 Classpath 断链、模块可见性缺失、ClassLoader 上下文错位等 阅读详情

  在最初学习java时,我们都知道我们编写的java代码在执行前会被编写成class字节码文件,然后通过类加载器加载到jvm虚拟机中去执行,并开辟内存空间存储其中的字节码对象与初始化赋值。在平时编写代码时,我们其实也常常与类加载器打交道,比如反射调用,读取配置文件,动态代理等。。那么,类加载器又是如何工作的呢,其中又是怎么加载对象,给变量赋值的呢,这就是这次我要学习的问题了。
类加载的过程
类加载的生命周期分为加载、验证、准备、解析、初始化、使用、卸载,共七个步骤,其中加载、验证、准备、初始化、卸载这五个步骤的顺序是固定的,依次执行,而解析和使用的执行时间会视代码的编码情况来确认。
在这里插入图片描述
那么类在加载过程中都做了什么呢?
1.加载:
在加载阶段,虚拟机需要完成以下3件事情
(1) 通过一个类的全限定名来获取定义此类的二进制字节流
(2) 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
(3) 在Java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据的访问入口。
这里的加载和类的加载不是一个性质,这里是类加载器加载入jvm的第一步,通俗点讲就是类加载器根据类的全类名找到类在文件夹中的位置,将这个文件转换为二进制流,通过读取流,把对应的数据结构转换为jvm可运行的数据结构存储到jvm的方法区中,最后再在堆内存中生成一个字节码对象与这个方法区的数据结构对应。
这里我们再复习一下jvm虚拟机中的内存结构
在这里插入图片描述
2.验证:
确保类加载的正确性。一般情况由javac编译的class文件是不会有问题的,但是可能有人的class文件是自己通过其他方式编译出来的,这就很有可能不符合jvm的编译规则,这一步就是要过滤掉这部分不合法文件 
3.准备:
准备阶段是正式为类变量分配并设置类变量初始值的阶段,这些内存都将在方法区中进行分配(因为这里的变量都是类变量,实例变量在堆,类变量在方法区),在这里进行的是初始化赋值,就是将类变量的值赋为默认值,如int为0,boolean为false,引用为null等等。。下面是例子

	public static int value = 123;
	value在准备阶段过后的初始值为0而不是123,而把value赋值的putstatic指令将在初始化阶段才会被执行

4.解析:
解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行。
符号引用是在class字节码文件最初未被jvm虚拟机执行的时候不知道实际的地址,所以由符号来代替,在解析后,再转换成虚拟机可以识别的直接引用。
5.初始化:
类初始化阶段是类加载过程的最后一步,到了初始化阶段,才真正开始执行类中定义的java程序代码。在准备阶段变量已经付过一次系统要求的初始值,而在初始化阶段,则根据代码中编写的赋值去初始化类变量和其他资源
6.使用和卸载:
到这两个阶段的时候类的加载其实已经进入了尾声,内存中已经为类创建了对应的内存空间,为相应的变量赋值,并完成代码中的使用过程与使用过后的销毁。
到此,类的加载过程就已经解析完了,那么类中各种属性的加载时间与加载顺序又是什么样的呢?
类加载器的加载机制与加载顺序
类加载器在java中有三个内置的类加载器,他们负责加载不同的类。
(1) Bootstrap ClassLoader : 将存放于<JAVA_HOME>\lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如 rt.jar 名字不符合的类库即使放在lib目录中也不会被加载)类库加载到虚拟机内存中。启动类加载器无法被Java程序直接引用
(2) Extension ClassLoader : 将<JAVA_HOME>\lib\ext目录下的,或者被java.ext.dirs系统变量所指定的路径中的所有类库加载。开发者可以直接使用扩展类加载器。
(3) Application ClassLoader : 负责加载用户类路径(ClassPath)上所指定的类库,开发者可直接使用。
类加载器使用的是双亲委派机制,来进行加载类。
双亲委派机制的原理:
如果一个类加载器接收到了类加载的请求,它首先把这个请求委托给他的父类加载器去完成,每个层次的类加载器都是如此,因此所有的加载请求都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它在搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。
好处:
java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,它存放在rt.jar中,无论哪个类加载器要加载这个类,最终都会委派给启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果用户自己写了一个名为java.lang.Object的类,并放在程序的Classpath中,那系统中将会出现多个不同的Object类,java类型体系中最基础的行为也无法保证,应用程序也会变得一片混乱。
类在加载时的执行顺序,代码如下:

public class Test {
    private static Test test = new Test();
    private static final int FINALNUM = 123;
    private int num = 111;
    private static int staticNum = 99;
    {
        System.out.println("FINALNUM="+FINALNUM+",staticNum="+staticNum+",num="+num);
        System.out.println("=========1===========");
    }
    static {
        System.out.println("FINALNUM="+FINALNUM+",staticNum="+staticNum);
        System.out.println("**********2**********");
    }
    public Test() {
        System.out.println("FINALNUM="+FINALNUM+",staticNum="+staticNum+",num="+num);
        System.out.println("----------3----------");
    }
    public static void main(String[] args) {
        System.out.println("FINALNUM="+FINALNUM+",staticNum="+staticNum);
        System.out.println("##########4###########");
    }
}

执行结果:
在这里插入图片描述
这里就要说一下类加载器的加载顺序了,为什么13会在最上方,13的staticNum会为0,所有的FINALNUM都会有值呢
总结:
因为类在加载类变量的时候会在准备阶段先把int的值赋值为0默认值,并且类加载器在加载静态变量时,是按照代码的执行顺序来加载的,也就是说会先执行静态的实例化对象的过程,而在实例化对象时,构造代码块的执行又是最优先级的,所以出现了这样的执行顺序,而被final修饰的变量,在加载时会被类认为是不再改变的,所以会优先直接写入到内存中,所以始终会被读取到值

为什么通过 类加载器 (ClassLoader) 可以访问静态文件,为什么要使用 this.getClass() 来获取,并且该文件是如何被加载的? 🏆 本文收录于《全栈Bug调优(实战版)》专栏,致力于分享我在项目实战过程中遇到的各Bug及其原因,并提供切实有效的解决方案。无论你是初学者还是经验丰富的开发者,本文将为你指引出一条更高效的Bug修复之路,助你早日登顶,迈向财富自由的梦想🚀!同时,欢迎大家关注、收藏、订阅本专栏,更多精彩内容正在持续更新中。让我们一起进步,Up!Up!Up!    备注: 部分问题/难题源自互联网,但经过精心筛选和整理,保证每一条解决方案都经过实战验证,真实可靠。 阅读详情

相关推荐

YOLOv8自动驾驶系统 —— 夜间低光照条件 详细说明和完整代码

本文提出一种针对夜间低光照优化的自动驾驶车道保持系统方案,基于YOLOv8模型改进,包含三大核心技术:1.采用Retinex理论的多尺度低光增强算法,结合自适应伽马校正;2.改进YOLOv8的车道检测模型,通过夜间专用数据集训练,增加抗眩光处理;3.多传感器融合框架,整合可见光红外图像。系统实现动态逆透视变换和参数调整,在Jetson Orin硬件上达到30ms级实时性能。测试显示在无照明、眩光干扰等极端场景下保持稳定,代码已开源。扩展方向包括V2X协同定位和自适应大灯联动控制。

u010117029的博客 584

深入理解Java:类加载机制及反射

 说明:本文乃学习整理参考而来. 一、Java类加载机制 1.概述        Class文件由装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数,属性和方法等,Java允许用户借由这个Class相关的元信息对象间接调用Class对象的功能。       虚拟机把描述的数据从class文件加载到内存,并对...

weixin_34378922的博客 611

华为OD机试双机位C卷:流量波峰 (C/C++/Py/Java/Js/Go)

华为OD机试双机位C卷 流量波峰,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解。华为OD机试 - 流量波峰。

qq_45776114的博客 2412

深入理解Java:类加载机制反射

一、Java类加载机制 1.概述 Class文件由装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数,属性和方法等,Java允许用户借由这个Class相关的元信息对象间接调用Class对象的功能。 虚拟机把描述的数据从class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java

fengjie_123的专栏 676

java类加载器笔记

类加载 java

leede123456的博客 240

【潜意识Java】深挖Java的ClassLoader机制

除了上述三种默认的类加载器,我们还可以自定义类加载器。自定义类加载器可以满足一些特殊的需求,比如从网络、数据库等非传统文件系统中加载,或者对的字节码进行加密和解密等操作。要实现自定义类加载器,通常需要继承,并重写findClass方法。System.out.println("对象的类加载器: " + obj.getClass().getClassLoader());在这个自定义类加载器的例子中,我们继承了。

潜意识Java的博客 852

Java的类加载器

Java基础、Java类加载器学习记录

景川的博客 1142

深入理解ClassLoader工作机制:class文件,ClassLoader,四大类加载器,双亲委托 以及好处坏处

深入理解ClassLoader工作机制:class文件,ClassLoader,四大类加载器,双亲委托 以及好处坏处

qq120631157的博客 5114

day36-类加载器

基础加强包含了:反射,动态代理,类加载器,xml,注解,日志,单元测试等知识点其中最难的是反射和动态代理,其他知识点都非常简单由于B站P数限制,xml,注解等知识点,阿玮写了详细文档供大家学习

2401_89213165的博客 697

[Java类加载器]Java中classLoader浅析.

[Java类加载器]Java中classLoader浅析. 本文为在公司内部TD上写的一篇小文, 主要讲解java中classLoader基础知识, 现在拿来这里分享一下. 一、问题 请在Eclipse中新建如下,并运行它: 1 package java.lang; 2 3 public class Long { 4 public sta...

weixin_39941921的博客 123

Java虚拟机探究第2讲: 类加载器ClassLoader

由于篇幅有限,这里就不一一罗列了,20道常见面试题(含答案)+21条MySQL性能调优经验小编已整理成Word文档或PDF文档还有更多面试复习笔记分享如下加入社区:https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0406579)]还有更多面试复习笔记分享如下[外链图片转存中…(img-HK4I4GQE-1725677406580)]

2401_86984580的博客 486

Java内存管理-掌握类加载器的核心源码和设计模式(六)

勿在流沙筑高台,出来混迟早要还的。 做一个积极的人 编码、改bug、提升自己 我有一个乐园,面向编程,春暖花开! 上一篇文章介绍了类加载器以及类加载器的双亲委派模型,让我们能够从整体上对类加载器有一个大致的认识,本文会深入到类加载器源码分析,了解类加载器ClassLoader中核心的源码,并且分析ClassLoader中的设计思想或者设计模式! 本文地图: 一、ClassLoader核...

阿飞云漫步 979

学习总结分享-MySQL的优化(完结篇)

在日常代码开发中,我们总是要写各种各样的sql语句,一段程序或者说一次客户端服务端的交互,最能影响执行速度的就是网络的传输和底层数据的存取等。。那么底层数据的存取如果是使用的是磁盘存储的关系型数据库,那么就是依靠sql语句了,所以,一个或者一组sql的执行效率,直接的影响到了程序的执行速度和用户体验,所以我们在编程时,要学会sql的优化,最大化的优化sql的执行时间,这样不仅可以增加执行速度,还...

VolcanoWec的博客 816

学习总结分享-浅析java的多态策略模式

  多态,是java三大面向对象的特性之一,其他还有封装和继承,有时人们也会将抽象算进去,称为四大特性。在日常写代码时,我们基本每天都在看到使用到多态,那么,什么是多态呢,又该怎么正确使用呢,这就是今天要去研究的了。。 1.什么是多态:   其实提到多态就不得不提到继承,因为要实现多态,首先第一点必须要有继承一个父,然后重写或实现其中的方法,最后用最简单的一句话就是:父型的引用指向子型的对象...

VolcanoWec的博客 612

学习总结分享-数据库的事务锁入门

这次的事务和锁研究,主要是MySQL数据库的innodb引擎,说到数据库,就免不了要说事务和锁机制,这是数据库最重要的组成部分。 什么是事务? 事务(Transaction)是并发控制的基本单位。所谓的事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位 数据库事务(简称:事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。(摘自百科) ...

VolcanoWec的博客 385

学习总结分享-Spring IOC容器的常用注解生命周期

经过上次的学习,已经初步的了解了Spring IOC的简单容器是如何编写的,也大体明白了Spring IOC容器的作用原理,那么如何才能使用好Spring IOC使其可以为我们正确的生成实体bean,正确的注入属性呢。 Spring 基于xml文件方式生成bean: 我们上次的学习就是通过配置文件的方式自己手写的简单IOC容器,而Spring已经为我们封装好了方法,只需要通过正确的xml配置,就...

VolcanoWec的博客 357

学习总结分享-spring篇之IOC(控制反转)浅析

概述 IOC 的作用: 解耦、单例缓存、Bean生命周期管理、父子容器 IOC 工作要经历2个过程: 启动预加载BeanDefination、实例化对象且缓存单例,传统BeanFactory的实现是懒加载(loadClass时再实例化bean),而web容器实现是预加载(启动和实例化一起进行)。但是BeanDefination都是预加载的。 IOC的作用 1、解耦: 实现了依赖关系的解耦,...

VolcanoWec的博客 334

学习总结分享-常用Map集合之HashMap原理浅析

Map是一种以(key,value)键值对的形式来存储数据的集合体系,其中HashMap也是这个体系中最常用的集合之一,他的查询速度增删的速度都十分的快,存取是无序的,并且其中键值对中的键(key)值不能重复,重复则替换之前的value值,那么就引申出几个问题。 1.常见的集合还有哪些? LinkedHashMap,HashMap的区别为他的存取顺序是有序的,因为他的 HashTa...

VolcanoWec的博客 311

学习总结分享-MySQL的MVCC(多版本并发控制)浅析

我们在平时编码操作数据库时,通常会有一个事务A读取一行数据,而又有另一个事务B需要写同一条数据,而为了保证事务A在每次读取时保持一致性和原子性,在传统的事务的锁机制下,这肯定是不允许的,事务B需要等待事务A执行结束后才可以执行,而当似的需求并发过多的时候,就很容易产生锁阻塞、死锁或者事务一直在等待执行过慢导致报错等等情况,所以数据库就使用了MVCC这个概念来解决事务在并发下的效率问题。 什么是M...

VolcanoWec的博客 286

学习总结分享-设计模式之代理模式入门

设计模式 设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分的、代码设计经验的总结。 使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。(-----摘自百度百科) 人们所熟知的设计模式共有23种,这次要研究的是其中的一种在日常开发中很常见的模式之一,代理模式。...

VolcanoWec的博客 271

cronolog-1.6.2.tar.gz cronolog-1.6.2下载

cronolog-1.6.2下载。日志轮询工具cronolog,推荐设置按天轮询或按小时轮询,解决应用日志过大问题。(文件全称:cronolog-1.6.2.tar.gz)

上一篇: 学习总结与分享-浅析java的多态与策略模式
下一篇: 学习总结与分享-MySQL数据库索引底层原理入门浅析
VolcanoWec
博客等级 码龄7年 0粉丝 24原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值