JVM类加载(类加载过程、双亲委派模型)

简介: JVM类加载(类加载过程、双亲委派模型)

一、类加载过程

对于一个类来说,它的生命周期是这样的:

1.加载

加载Loading)阶段是整个类加载Class Loading)过程中的一个阶段,它和类加载Class

Loading 是不同的,一个是加载 Loading 另一个是类加载 Class Loading ,所以不要把二者搞混了。

在加载 Loading 阶段, Java 虚拟机需要完成以下三件事情:

1 )通过一个类的全限定名来获取定义此类的二进制字节流。

2 )将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。

3 )在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各种数据的访问入口

2.验证

验证是连接阶段的第一步,这一阶段的目的是确保Class文件的字节 流中包含的信息符合《Java虚拟机规范》的全部约束要求,保证这些信 息被当作代码运行后不会危害虚拟机自身的安全。

验证选项:

文件格式验证

字节码验证

符号引用验证 ...

3.准备

准备阶段是正式为类中定义的变量(即静态变量,被 static 修饰的变量)分配内存并设置类变量初始值的阶段。

比如此时有这样一行代码:

public static int value = 123;
//它是初始化 value 的 int 值为 0,而非 123。

4.解析

解析阶段是Java 虚拟机将常量池内的符号引用替换为直接引用的过程,也就是初始化常量的过程。

5.初始化

初始化阶段,Java 虚拟机真正开始执行类中编写的Java 程序代码,将主导权移交给应用程序。初始化阶段就是执行类构造器方法的过程。


二、关于类加载的典型试题

这段代码的输出结果是什么?

class A{
    public A(){
        System.out.println("A的构造方法");
    }
    {
        System.out.println("A的构造代码块");
    }
    static {
        System.out.println("A的静态代码块");
    }
}
class B extends A{
    public B(){
        System.out.println("B的构造方法");
    }
    {
        System.out.println("B的构造代码块");
    }
    static {
        System.out.println("B的静态代码块");
    }
}
public class test extends B{
    public static void main(String[] args) {
        new test();
        new test();
    }
}

解析:

我们的程序是从main开始执行的,那么main这里是test方法,所以,要执行main,就要先加载test。也就是说,在加载test类的时候,此时还没执行main。

我们的程序是从main开始执行的,那么main这里是test方法,所以,要执行main,就要先加载test。也就是说,在加载test类的时候,此时还没执行main。

test继承自B,要加载test,那么就要先加载B;

B继承自A,要加载B,那么就要先加载A;

总之,只要这个类被用到了,就要先加载这个类(实例化、调用方法、调用静态方法,被继承...都算被用到)。

然后,要想要构造test,就得先构造B,要想构造B,就得先构造A,那么对于A来说,构造过程 = 构造代码块的执行 + 构造方法的执行。

还有,静态的只执行一次,所以输出结果是:


三、双亲委派模型

双亲委派模型是类加载中的一个环节,这环节处于Loading阶段。

双亲委派模型,描述的就是JVM中的类加载器,如何根据类的全限定名( java.lang.String )找到.class文件的过程。

JVM里提供了专门的对象,叫做类加载器,负责进行类加载.当然找文件的过程也是类加载器来负责的。


.class 文件,可能放置的位置有很多.有的要放到JDK目录里,有的放到项目目录里,还有的在其他特定位置,因此JVM里面提供了多个类加载器,每个类加载器负责一个片区。


默认的类加载器主要是三个:

1.BootStrapClassLoader负责加载标准库中的类(String, ArrayList, Random, Scanner..)

2.ExtensionClassLoader负责加载JDK扩展的类.(现在很少会用到)

3.ApplicationClassLoader 负责加载当前项目目录中的类~~

其实程序猿还可以自定义类加载器,来加载其他目录中的类。Tomcat就自定义了类加载器,用来专门加载 webapps里面的.class 。双亲委派模型,就描述了这个找目录过程,也就是上述类加载器是如何配合的。


1.加载java.lang.String

a.程序启动,先进入ApplicationClassLoader类加载器

b.ApplicationClassLoader就会检查下,它的父加载器是否已经加载过了.如果没有,就调用父类加载器ExtensionClassLoader

c. ExtensionClassLoader也会检查下,它的父加载器是否加载过了.如果没有,就调用父类加载器BootStrapClassLoader

d.BootStrapClassLoader也会检查下,它的父加载器是否加载过,自己没有父亲~~于是自己扫描自己负责的目录

e. java.lang.String这个类在标准库中能找到! 直接由BootStrapClassLoader负责后续的加载过程.查找环节就结束了

2.加载自己写的test类

a.程序启动,先进入ApplicationClassLoader类加载器

b.ApplicationClassLoader就会检查下,它的父加载器是否已经加载过了.如果没有,就调用父类加载器ExtensionClassLoader

c. ExtensionClassLoader也会检查下,它的父加载器是否加载过了.如果没有,就调用父类加载器BootStrapClassLoader

d.BootStrapClassLoader也会检查下,它的父加载器是否加载过,自己没有父亲~~于是自己扫描自己负责的目录,如果没有扫描到,就回到子加载器继续扫描。

e.ExtensionClassLoader也扫描自己的目录,如果没有扫描到,就回到子加载器继续扫描。

f.ApplicationClassLoader也扫描自己负责的目录,能找到test类,于是进行后续加载,查找目录的环节结束。

304882a17691456cbd6d24265a47e823.png


相关文章
|
5月前
|
安全 Java
对 JVM 的类加载机制以及寻找字节码文件的“双亲委派模型”的理解
对 JVM 的类加载机制以及寻找字节码文件的“双亲委派模型”的理解
34 0
|
16天前
|
安全 Java 应用服务中间件
JVM常见面试题(三):类加载器,双亲委派模型,类装载的执行过程
什么是类加载器,类加载器有哪些;什么是双亲委派模型,JVM为什么采用双亲委派机制,打破双亲委派机制;类装载的执行过程
JVM常见面试题(三):类加载器,双亲委派模型,类装载的执行过程
|
6天前
|
存储 算法 Java
深入解析 Java 虚拟机:内存区域、类加载与垃圾回收机制
本文介绍了 JVM 的内存区域划分、类加载过程及垃圾回收机制。内存区域包括程序计数器、堆、栈和元数据区,每个区域存储不同类型的数据。类加载过程涉及加载、验证、准备、解析和初始化五个步骤。垃圾回收机制主要在堆内存进行,通过可达性分析识别垃圾对象,并采用标记-清除、复制和标记-整理等算法进行回收。此外,还介绍了 CMS 和 G1 等垃圾回收器的特点。
19 0
深入解析 Java 虚拟机:内存区域、类加载与垃圾回收机制
|
2月前
|
存储 算法 Java
JVM组成结构详解:类加载、运行时数据区、执行引擎与垃圾收集器的协同工作
【8月更文挑战第25天】Java虚拟机(JVM)是Java平台的核心,它使Java程序能在任何支持JVM的平台上运行。JVM包含复杂的结构,如类加载子系统、运行时数据区、执行引擎、本地库接口和垃圾收集器。例如,当运行含有第三方库的程序时,类加载子系统会加载必要的.class文件;运行时数据区管理程序数据,如对象实例存储在堆中;执行引擎执行字节码;本地库接口允许Java调用本地应用程序;垃圾收集器则负责清理不再使用的对象,防止内存泄漏。这些组件协同工作,确保了Java程序的高效运行。
19 3
|
2月前
|
C# UED 开发者
WPF动画大揭秘:掌握动画技巧,让你的界面动起来,告别枯燥与乏味!
【8月更文挑战第31天】在WPF应用开发中,动画能显著提升用户体验,使其更加生动有趣。本文将介绍WPF动画的基础知识和实现方法,包括平移、缩放、旋转等常见类型,并通过示例代码展示如何使用`DoubleAnimation`创建平移动画。此外,还将介绍动画触发器的使用,帮助开发者更好地控制动画效果,提升应用的吸引力。
64 0
|
3月前
|
存储 前端开发 Java
(二)JVM成神路之剖析Java类加载子系统、双亲委派机制及线程上下文类加载器
上篇《初识Java虚拟机》文章中曾提及到:我们所编写的Java代码经过编译之后,会生成对应的class字节码文件,而在程序启动时会通过类加载子系统将这些字节码文件先装载进内存,然后再交由执行引擎执行。本文中则会对Java虚拟机的类加载机制以及执行引擎进行全面分析。
|
3月前
|
Java Perl
JVM内存问题之如何统计在JVM的类加载中,每一个类的实例数量,并按照数量降序排列
JVM内存问题之如何统计在JVM的类加载中,每一个类的实例数量,并按照数量降序排列
|
3月前
|
存储 安全 Java
开发与运维引用问题之JVM类加载过程如何解决
开发与运维引用问题之JVM类加载过程如何解决
22 0
|
3月前
|
存储 算法 Java
JAVA程序运行问题之Java类加载到JVM中加载类时,实际上加载的是什么如何解决
JAVA程序运行问题之Java类加载到JVM中加载类时,实际上加载的是什么如何解决
|
4月前
|
安全 前端开发 Java
《JVM由浅入深学习【一】 》JVM由简入深学习提升(类加载过程+父子类加载过程+类加载器+双亲委派机制)
《JVM由浅入深学习【一】 》JVM由简入深学习提升(类加载过程+父子类加载过程+类加载器+双亲委派机制)
33 0