类加载机制和双亲委派机制

简介: 类加载机制和双亲委派机制


🍊 类加载机制和双亲委派机制

第一步,加载,一个Java源文件进行编译之后,成为一个class字节码文件存储在磁盘上面,这个时候jvm需要读取这个字节码文件,通过通过IO流读取字节码文件,这一步就是加载。

类加载器将.class文件加载到JVM,首先是看当前类是不是使用自定义加载类加载的,如果不是,就委派应用类加载器加载,如果有加载过这个class文件,那就不用再加载了。如果没有,那么会拿到父加载器,然后调用父加载器的loadClass方法。父类的扩展类加载器同理也会先检查自己是不是已经加载过,如果没有再往上,看看启动类加载器。到启动类加载器,已经没有父加载器了,这时候开始考虑自己是否能加载了,如果自己加载不了,就会下沉到子加载器去加载,一直到最底层,如果没有任何加载器能加载,就会抛出ClassNotFoundException找不到类异常,这就是所谓的双亲委派机制。

这种机制可以避免,同路径下的同文件名的类,比如,自己写了一个java.lang.obejct,这个类和jdk里面的object路径相同,文件名也一样,这个时候,如果不使用双亲委派机制的话,就会出现不知道使用哪个类的情况,而使用了双亲委派机制,它就委派给父类加载器就找这个文件是不是被加载过,从而避免了上面这种情况的发生。

第二步,验证,JVM读到文件也不是直接运行,还需要校验加载进来的字节码文件是不是符合JVM规范

验证的第一步就是文件的格式验证,验证class文件里面的魔数和主次版本号,发现它是一个jvm可以支持的class文件并且它的主次版本号符合兼容性要求,所以验证通过。

第三步,加载,它会将class文件这个二进制静态文件转化到方法区里面,转化为方法区的时候,会有一个结构的调整,将静态的存储文件转化为运行时数据区,这个转化等于说又回到了加载。

接着到了方法区的运行时数据区以后,在java堆内存里面生成一个当前类的class对象,作为方法区里面这个类,被各种访问的一个入口。比如说object类,它是所有类都继承它,访问它,所以它也需要一个被各种类访问的入口。object类先加载,加载完成之后,它经过这一系列的操作,把自己java.lang.object放到这个堆里面,要让其他的类进行访问,这个也是加载。

第四步,继续验证,接着元数据验证,它会对字节码描述的信息进行语义分析,比如:这个类是不是有父类,是不是实现了父类的抽象方法,是不是重写了父类的final方法,是不是继承了被final修饰的类等等。

然后字节码验证,通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的,比如:操作数栈的数据类型与指令代码序列是不是可以配合工作,方法中的类型转换是不是有效等等。

最后符号引用验证:确保解析动作可以正确执行,比如说:通过符号引用是不是可以找到对应的类和方法,符号引用中类、属性、方法的访问性是不是能被当前类访问等,验证完成之后,需要做准备。

第五步,分配内存空间,准备就是给类的静态变量分配内存,并赋予默认值。我们的类里,可能会包含一些静态变量, 比如说public static int a = 12; 得给a这个变量分配个默认值 0,再比如public static User user = new User(); 给 static的变量User分配内存,并赋默认值null。如果是final修饰的常量,就不需要给默认值了,直接赋值就可以了。

第六步,解析,解析就是将符号引用变为直接引用,该阶段会把一些静态方法替换为指向数据储存在内存中的指针或者句柄,也就是所谓的直接引用,这个就是静态链接过程,是在初始化之前完成。有静态链接就有动态链接,动态链接是在程序运行期间完成将符号引用替换为直接引用,比如静态方法里面有个方法,在运行的时候,方法是存放在常量池中的符号,运行到这个符号,就是找这个符号对应的方法区,因为代码的指令是加载到方法区里面去的,最后把方法对应代码的地址放到栈帧中的动态链接里。

  • 编译器中的解析阶段其目的是将符号引用(如变量、函数等名字)转换成直接引用(如指向内存中的地址),从而使程序能够正确地执行。
  • 直接引用是指程序中直接使用的方法或数据在内存中对应的地址。在程序编译期间,编译器将所有的方法和数据按照一定的规则映射到内存中的不同位置,生成可执行文件。在程序运行期间,程序通过直接引用来访问这些方法和数据,直接引用一般是一个绝对地址或偏移量。因此,在程序运行时,操作系统需要将程序中的符号引用转换成直接引用,以正确地访问方法和数据。
  • 符号引用是指程序中使用的方法或数据的标识符,不是直接的内存地址。在编译期间,编译器不能确定符号引用对应的具体地址,因为这些方法和数据在运行时可能会被加载到不同的内存地址上。因此,在编译期间,编译器将符号引用记录在符号表中,并在链接期间将符号引用解析为直接引用。在操作系统加载程序之前,链接器会根据符号表中的信息,找到并解析程序中所有的符号引用,将它们转换为直接引用。
  • 静态链接是指将程序中所有需要用到的代码和数据在编译时就全部链接成一个可执行文件的过程。在静态链接过程中,编译器会将静态库中的函数和变量复制到可执行文件中,形成一个完整的可执行文件。在程序运行时,所有的代码和数据都存在于内存中,程序不需要再依赖外部库文件或动态链接库。静态链接的缺点是可执行文件较大,不易于维护和更新。
  • 动态链接是一个程序运行时(运行期间)连接目标文件模块的过程,将需要的代码添加到进程的地址空间中,并将不同的模块组合在一起,使它们能够相互调用。在动态链接的过程中,程序中的符号引用被动态解析为直接引用,这样程序才能正确地访问方法和数据。动态链接的好处是减小了程序的大小,同时也方便了程序的更新和维护。常见的动态链接库(DLL)就是使用动态链接方式加载的。
  • 在静态链接过程中,一些静态方法会被替换成直接引用,这个过程在程序初始化之前完成。动态链接是在程序运行期间完成,它会将符号引用替换成直接引用,使程序能够正确地访问方法和数据。具体来说,动态链接会将符号引用对应的方法的代码地址放到栈帧中的动态链接里,从而实现符号引用到直接引用的转换。

第七步,初始化了,初始化就是对类的静态变量初始化为指定的值并且会执行静态代码块。比如准备阶段的public static final int a = 12;这个变量,就是准备阶段给static变量a赋了默认值0,这一步就该把12赋值给它了。还有static的User public static User user = new User(); 把User进行实例化。

第八步,就是使用和卸载了,到此整个加载流程就走完了。


🔔如果您需要转载或者搬运这篇文章的话,非常欢迎您私信我哦~

相关文章
|
前端开发
异步转同步的几种方法
在循环等待中,我们可以使用一个变量来指示异步操作是否已完成。然后,我们可以在循环中检查该变量,如果它指示异步操作已完成,则退出循环。
765 0
|
安全 算法 网络协议
一文带你搞懂HTTP和HTTPS
一文带你搞懂HTTP和HTTPS
361 0
|
Java 数据库连接
什么是双亲委派?如何打破双亲委派?
什么是双亲委派?如何打破双亲委派?
282 0
|
SQL 分布式计算 大数据
黑马程序员-大数据入门到实战-分布式SQL计算 Hive 入门
黑马程序员-大数据入门到实战-分布式SQL计算 Hive 入门
312 0
|
SQL 存储 关系型数据库
关于主从延迟,一篇文章给你讲明白了!
关于主从延迟,一篇文章给你讲明白了!
227 1
|
8月前
|
人工智能 安全 测试技术
刚刚,多模态推理模型QVQ全新开源
刚刚,多模态推理模型QVQ全新开源
|
12月前
|
SQL 存储 关系型数据库
美团面试:binlog、redo log、undo log的底层原理是什么?它们分别实现ACID的哪个特性?
老架构师尼恩在其读者交流群中分享了关于 MySQL 中 redo log、undo log 和 binlog 的面试题及其答案。这些问题涵盖了事务的 ACID 特性、日志的一致性问题、SQL 语句的执行流程等。尼恩详细解释了这些日志的作用、所在架构层级、日志形式、缓存机制以及写文件方式等内容。他还提供了多个面试题的详细解答,帮助读者系统化地掌握这些知识点,提升面试表现。此外,尼恩还推荐了《尼恩Java面试宝典PDF》和其他技术圣经系列PDF,帮助读者进一步巩固知识,实现“offer自由”。
美团面试:binlog、redo log、undo log的底层原理是什么?它们分别实现ACID的哪个特性?
|
Java 编译器
什么是双亲委派机制?
什么是双亲委派机制?
411 59
|
11月前
|
存储 Linux 文件存储
Linux文件系统
Linux文件系统 一切皆文件 在Linux中,“一切皆文件”的概念意味着系统中的所有资源,包括硬件设备、目录及进程等,均被视为文件。这种设计简化了操作和管理,具体包括: 普通文件:存储数据的常规文件。 目录文件:包含其他文件和子目录的文件。 进程文件:在/proc目录下代表系统中运行的进程。 设备文件:位于/dev目录,代表硬件设备。 网络字节流套接字文件:用于网络通信的数据流。 链接文件:指向另一个文件的符号链接或硬链接。 管道文件:用于进程间通信的文件。
167 7
|
12月前
|
Java
JVM进阶调优系列(5)CMS回收器通俗演义一文讲透FullGC
本文介绍了JVM中CMS垃圾回收器对Full GC的优化,包括Stop the world的影响、Full GC触发条件、GC过程的四个阶段(初始标记、并发标记、重新标记、并发清理)及并发清理期间的Concurrent mode failure处理,并简述了GC roots的概念及其在GC中的作用。