java类加载时执行一次_Java类加载机制,你了解吗?

1、类的加载

类的加载是指将类的.class文件读取进内存中,并将其放在JVM运行时数据区的方法区内,然后在堆中创建一个java.lang.Class对象,用于封装类在方法区中的数据结构,同时作为方法区数据的访问入口。

2、类的生命周期

类的生命周期指一个class文件从加载到卸载的整个过程676eac95cfe3b0be1e244983942b91f0.png

3、类的加载过程

JVM将类的加载分为三个阶段:装载(Load)、链接(Link)、初始化(Initialize)

3.1 装载:查找并加载类的二进制数据

在硬盘上查找并通过IO读入字节码文件,使用到类时才会加载,例如调用类的main()方法,new对象等等,在加载阶段会在内存中生成一个代表这个类的Java.lang.Class对象,作为方法区这个类的各种数据的访问入口。

3.2 链接:验证、准备、解析验证

校验字节码文件的正确性、安全性,包括四种验证:文件格式验证、元数据的验证、字节码验证、符号引用验证

准备

为类变量(static修饰的字段变量)分配内存并且设置该类变量的初始值,这里不包含final修饰的static,因为final在编译的时候就已经分配了。也不会为实例变量分配初始化,实例变量会随着对象分配到堆内存中。

解析

把常量池中的符号引用转换为直接引用,静态链接过程

3.3 初始化:初始化静态变量,执行静态代码块

3.3.1 类的初始化时机

如果一个类被直接引用,就会触发类的初始化。在Java中,直接引用的情况有:通过new关键字实例化对象、读取或设置类的静态变量、调用类的静态方法

通过反射执行以上三种行为

初始化子类的时候,会触发父类的初始化

作为程序的入口直接运行时(main方法)502adda9532515a344865dc9d35d51b1.png

3.3.2 类初始化步骤假如这个类还没有被加载和链接,则程序先加载并连接该类(动态加载:主类在运行过程中如果使用到其他类,会逐步加载这些类 eg:jar包和war包中的类并不是一次性都加载到内存中,而是使用时才加载)

假如该类的直接父类还没有被初始化,则先初始化其直接父类

假如类中有初始化语句,则系统依次执行这些初始化语句ae0a60bdadbf70e46ed737f70005a3a9.png

4、类加载后方法区存储内容

类被加载到方法区中后主要包含运行时常量池、类型信息、字段信息、方法信息、类加载器的引用、对应class实例的引用等信息。

类加载器的引用:这个类到类加载器实例的引用

对应class实例的引用:类加载器在加载类信息放到方法区中后,会创建一个对应的Class 类型的对象实例放到堆(Heap)中, 作为开发人员访问方法区中类定义的入口和切入点。

5、类加载器

类加载过程主要通过类加载器实现,Java中有以下几种类加载器:引导类加载器(Bootstrap ClassLoader)

负责加载支撑JVM运行的位于JRE的lib目录下的核心类库,比如rt.jar\charsets.jar等,由C++实现,不是ClassLoader子类,Java程序无法直接引用。

拓展类加载器(Extension ClassLoader)

负责加载支撑JVM运行的位于JRE的lib目录下的ext拓展目录中的类库

应用类加载器(App ClassLoader)

负责加载ClassPath路径下的类包,主要加载开发人员写的类

自定义类加载器(Custom ClassLoader)

负责加载用户自定义路径下的类包

类加载器之间存在父子层级结构:be8e3d90ad20fe36121339dcae637339.png

46159ac90826117e0d3c55c09638868a.png

f6303f42a79274f424f45384c8940c7c.png

2f3a03e71c1e71396fa603b2f55ec774.png

6、双亲委派机制

6.1 定义

双亲委派机制是指当一个类加载器收到一个类加载请求时,该类加载器首先会把请求委派给父类加载器。每个类加载器都是如此,只有在父类加载器在自己的加载路径下找不到指定类时,子类才会尝试自己去加载。

6.2 工作过程995a9a2c1c044d3845542de360fb841e.png当应用程序类加载器收到一个类加载请求时,他首先不会自己去尝试加载这个类,而是将这个请求委派给父类加载器Extension ClassLoader去完成。

当Extension ClassLoader收到一个类加载请求时,他首先也不会自己去尝试加载这个类,而是将请求委派给父类加载器Bootstrap ClassLoader去完成。

如果Bootstrap ClassLoader加载失败(在\lib中未找到所需类),就会让Extension ClassLoader尝试加载。

如果Extension ClassLoader也加载失败,就会使用Application ClassLoader加载。

如果Application ClassLoader也加载失败,就会使用自定义加载器去尝试加载。

如果均加载失败,就会抛出ClassNotFoundException异常。

6.3 双亲委托机制实现源码(JDK 1.8)f9cb98178c70d577ec9987faf2a6f898.png

6.4 双亲委托作用沙箱安全机制:防止核心类库被篡改,自己写的java.lang.String不会被加载。

避免类的重复加载:当父加载器已经加载过该类时,子加载器就没必要重新加载一次,保证被加载类的唯一性。9531bad91c6a269a834e02b2e594a1c9.png

ecd2c43b1e8bc7877dfcad5be1248954.png

7、自定义类加载器94e9bf4fb35fd861a16c3602c55601c3.png

8、如何打破双亲委派机制

核心:继承ClassLoader,重写类加载方法,实现加载逻辑,不委托给双亲加载7474c49b24667d90b3ab7e71594b1041.png

efc308f355e9583dc389a0cd6555cfbf.png

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值