JJVM类的加载过程

类的加载过程

一个java文件从被加载到被卸载这个生命过程,总共要经理五个阶段,JVM将类加载过程分为:(加链初使卸

1. 加载

首先通过一个类的全限定名来获取此类的二进制字节流;其次将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;最后在java堆中生成一个代表这个类的Class对象,作为方法区这些数据的访问入口。总的来说就是查找并加载类的二进制数据。

2. 链接

验证:确保被加载类的正确性,字节码开头必须为cafebabe

准备:为类的静态变量分配内存,并将其初始化为默认值

解析:把类中的符号引用转换为直接引用

3. 类的初始化

1> 类什么时候才被初始化
  • 创建类的实例,也就是new一个对象

  • 访问某个类或接口的静态变量,或者对该静态变量赋值

  • 调用类的静态方法

  • 反射(Class.forName(类路径))

  • 初始化一个类的子类(会首先初始化子类的父类)

  • JVM启动时标明的启动类,即文件名和类名相同的那个类

    另外:

    1、类中的static final 修饰的基本数据类型及String类型成员变量,被访问是不会触发类初始化的;

    2、静态内部类也是被访问不会触发类初始化;

2>类的初始化顺序
  1. 如果这个类还没有被加载和链接,那先进行加载和链接

  2. 假如这个类存在直接父类,并且这个类还没有被初始化(注意:在一个类加载器中,类只能初始化一次),那就初始化直接的父类(不适用于接口)

  3. 加入类中存在初始化语句(如static变量和static块),那就一次执行这些初始化语句

  4. 总的来说,初始化顺序依次是:(静态变量、静态初始化块)->(变量、初始化块)-> 构造器

如果有父类,则顺序是:

父类static方法 -> 子类static方法 -> 父类构造方法 -> 子类构造方法

4. 类的加载

类的加载指的是将类的.class文件中的二进制数据读入内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个这个类的java.lang.Class对象。

先将类的字节码文件读入内存,放入方法区中,然后在堆中创建一个该类的Class对象

如:

image-20230812140421672

image-20230812140617240

类的加载的最终产品是位于堆中的Class对象。Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。加载类的方式有以下几种:

  1. 从本地系统直接加载

  2. 通过网络下载.class文件

  3. 从zip,jar等归档文件中加载.class文件

  4. 从专有数据库中提取.class文件

  5. 将Java源文件动态编译为.class文件(服务器)

5.加载器

JVM的类加载是通过ClassLoader及其子类来完成的,类的层次关系和加载顺序可以由下图来描述:

image-20230812141155707

加载器介绍:

1)BootstrapClassLoader(启动类加载器)   负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,加载System.getProperty(“sun.boot.class.path”)所指定的路径或jar。 2)ExtensionClassLoader(标准扩展类加载器)   负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包。载System.getProperty(“java.ext.dirs”)所指定的路径或jar。 3)AppClassLoader(系统类加载器)   负责记载classpath中指定的jar包及目录中class 4)CustomClassLoader(自定义加载器)   属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现。

(2)类加载器的顺序 1)加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载就视为已加载此类,保证此类只所有ClassLoader加载一次。而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。 2)在加载类时,每个类加载器会将加载任务上交给其父,如果其父找不到,再由自己去加载。

3)Bootstrap Loader(启动类加载器)是最顶级的类加载器了,其父加载器为null。

public class Demo {
    public static void main(String[] args) {
        C c = new C();
    }
}
class A{
    static {
        System.out.println("A static");
    }
}
​
class B extends A{
    static {
        System.out.println("B static");
    }
}
​
class D{
    static {
        System.out.println("D static");
    }
}
​
class C extends B{
    private static D d = new D();
    static {
        System.out.println("C static");
    }
}

打印

A static
B static
D static
C static

在上面的例子中,类C继承于B,B继承于A,C又依赖于D,在创建C时,会自动加载C继承的B和依赖的D,然后B又继承于A,先加载A,再加载B,再加载D,最后加载D

继承的优先级大于依赖

所有的变量初始化完,才会执行构造方法

在类的加载过程中,只有内部的变量创建完,才会去执行这个类的构造方法。

// 静态块 和 构造方法的加载顺序
public class ConstructorStep {
    public static void main(String[] args) {
        A2 a2 = new A2();
    }
}
​
class D2{
    static {
        System.out.println("D2 static");
    }
    public D2(){
        System.out.println("D2 constructor");
    }
}
​
class C2{
    static {
        System.out.println("C2 static");
    }
    public C2(){
        System.out.println("C2 constructor");
    }
}
​
class B2{
    C2 c2 = new C2();
    D2 d2 = new D2();
    static {
        System.out.println("B static");
    }
    public B2(){
        System.out.println("B2 constructor");
    }
}
​
class A2{
    B2 b2 = new B2();
    static {
        System.out.println("A static");
    }
    public A2(){
        System.out.println("A2 constructor");
    }
}

打印:

A static
B static
C2 static
C2 constructor
D2 static
D2 constructor
B2 constructor
A2 constructor
​

先创建A,执行A的静态块,再加载A的成员变量B2

执行B2的静态块,再加载B的成员变量C2,D2

执行C2的静态块,由于C2中没有成员变量需要加载,再执行C2的空参构造方法。

执行D2的静态块,同C2一样。

B2的成员变量加载完了,执行B2的构造方法

最后,A2同B2一样


总结

  1. 所有的类都会优先加载基类

  2. 静态成员的初始化优先

  3. 成员初始化完后,才会执行构造方法

  4. 静态成员的初始化与静态块的执行,发生在类加载的时候,静态成员的优先级大于静态块

  5. 类对象的创建以及静态块的访问,都会触发类的加载

执行顺序

静态成员变量 -> 静态代码块 -> 成员变量 -> 构造方法

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何在社交媒体中使用增强现实来提高客户参与度?

目录 1. 增强现实在社交媒体中的应用是如何发展的 2. 社交媒体营销和广告中的增强现实 3. 社交媒体上的增强现实滤镜和镜头 4. 社交媒体平台上的增强现实购物 5. 利用社交媒体的增强现实事件和品牌激活 6. 增强现实在社交媒体中的未来是什么 7. 社交媒体中的增强现实常见…

MTK i500p AIoT解决方案

一、方案概述 i500p是一款强大而高效的AIoT平台,专为便携式、家用或商用物联网应用而设计,这些应用通常需要大量的边缘计算,需要强大的多媒体功能和多任务操作系统。该平台集成了Arm Cortex-A73 和 Cortex-A53 的四核集群,工作频…

抖音引流私域转化模式1.0现场视频,从抖音源源不断把人加到私域买单

抖音-引流私域转化模式1.0现场视频,从抖音源源不断把人加到私域,让加到私域的粉丝买单 课程内容:抖音引流私域转化模式1.0现场视频,从抖音源源不断把人加到私域买单 - 百创网-源码交易平台_网站源码_商城源码_小程序源码 01.第一…

理解PostgreSQL中的postmaster.pid

在PG中,一个简要的体系结构图可以大致画成下边的样子: Server端基本上分成backend process和若干background process。这些process都是一个名为postmaster进程的子进程。而postmaster则是postgres进程的别名。 进程概况 [14:42:08-postgrescentos1:/pg…

脱单微信群|相亲脱单支招|手把手教你脱单

群里有太多优质单身男女生,你的脱单困惑,TA可能也遇到过。抬手在群里滴滴,即刻拥有一群有过相同问题的友友和运营客服帮忙。 点我进脱单群 点击 情感脱单问题,直接私信给樱桃情感老师,保护个人隐私和提升问题解决效率…

arcgis10.5安装步骤

目录 一、安装License 二、安装ArcGIS_Desktop 三、安装汉化包,解压后,直接双击等待安装即可 一、安装License 双击ArcGIS_License_Manager_Windows_105_154033 选择【Next】 勾选I accept,然后选择【Next】 选择License的安装目录&#x…

详解事件循环

浏览器的进程模型 何为进程? 程序运行需要有它自己专属的内存空间,可以把这块内存空间简单的理解为进程 每个应用至少有一个进程,进程之间相互独立,即使要通信,也需要双方同意。 何为线程 ? 有了进程后…

锂电池算法学习集合---基于matlab/simulink的电池参数辨识、充放电、SOC估计算法。

整理了锂电池的多种算法合集:涵盖电动汽车Simulink模型、电动汽车动力电池SOC估算模型、动力电池及电池管理系统BMS。 电动汽车动力电池SOC估算模型含有:电池参数辨识模型、电池的充放电数据、电池手册、卡尔曼滤波电池SOC文献、卡尔曼滤波算法的锂电池SOC估算模型…

15-1-Flex布局

个人主页:学习前端的小z 个人专栏:HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结,欢迎大家在评论区交流讨论! 文章目录 Flex布局1 Flex容器和Flex项目2 Flex 容器属性2.1 主轴的方向2.2 主轴对齐方式…

STM32智能家居小助手

​ 设计的目的 大部分家用电器开关仍旧是传统的机械式按键开关,原因是传统式的电器开关开发周期短,制作成本低,方案成熟,但是传统的遥控家电开关已经不能满足人们对家电控制的要求,传统的遥控器具有单一性,…

k8s1.28-helm安装kafka-Raft集群

参考文档 [Raft Kafka on k8s 部署实战操作 - 掘金 (juejin.cn)](https://juejin.cn/post/7349437605857411083?fromsearch-suggest)部署 Raft Kafka(Kafka 3.3.1 及以上版本引入的 KRaft 模式)在 Kubernetes (k8s) 上,可以简化 Kafka 集群…

Linux编程中进程的概念和环境变量

目录 概述 1 认识进程 1.1 进程的定义 1.2 进程状态 1.3 进程的调用 2 进程环境 2.1 进程ID 2.2 父进程与子进程 2.3 UID 和 GID 2.4 环境变量 2.4.1 通过main函数参数获取环境变量 2.4.2 environ 全局变量获取环境变量 2.4.3 getenv()函数获取环境变量 2.5 环境变…

Ubuntu22.04平台编译完美解决问题“error: GLSL 4.5 is not supported.”【GLSL(OpenGL着色器语言)】

GLSL介绍 GLSL(OpenGL着色器语言)是用于编写OpenGL着色器程序的语言。GLSL 4.5 是 GLSL 的一个版本,引入了许多新的特性和改进,旨在提高着色器编程的灵活性和性能。GLSL 4.5 工具通常是用于编写、调试和优化 GLSL 4.5 着色器代码…

Java基于微信小程序的校园外卖平台系统,附源码

博主介绍:✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇&#x1f3…

怎么将本地VScode与Linux云服务器上的Vscode联动起来

首先我们打开本地刚刚下好的VScode, 下载remote SSH插件 按下F1 找到该选项, 点击 然后输入ssh 用户名公网地址 点击选择第一个 此时你的VScode左侧栏里就会出现这个图标 点进来后就可以看到主机已经加载进来了(如果没有, 关闭VScode重进…

工业4g路由器联网后迅速掉线是什么原因?

工业4G路由器连接上网后迅速掉线可能是由多种因素造成的。以下是一些建议的检查和解决步骤: 1、信号问题: 信号强度:检查工业路由器信号强度指示灯,如果信号弱,尝试移动路由器位置或添加外部天线来增强信号。 网络拥…

绘画尝试1

提示词:Elegant woman, standing in a picturesque courtyard, slender figure, graceful posture, elegant back, smooth neck line, flashing charming eyes. 绘画成果:

机器学习和深度学习

一、定义 机器学习是一种人工智能领域的分支,旨在使计算机系统能够自动从数据中学习和提高性能,而不需要明确的编程。简而言之,机器学习是利用经验来训练计算机系统,使其能够从输入数据中提取规律,并对新数据进行预测…

百度松果菁英班——机器学习实践四:文本词频分析

飞桨AI Studio星河社区-人工智能学习与实训社区 🥪jieba分词词频统计 import jieba # jieba中文分词库 ​ with open(test.txt, r, encodingUTF-8) as novelFile:novel novelFile.read() # print(novel) stopwords [line.strip() for line in open(stop.txt, r,…

mac老版本如何升级到最新版本

mac老版本如何升级到最新版本 老macbook升级新版本(Big sur、Monterey) 首先介绍我的电脑的机型及情况: 2015年初的MacBook Air 处理器是1.6Hz 双核Interl Core i5 内存4G 老版本只能升到10.13 想要升到最高版本的原因:想要注册…