0
点赞
收藏
分享

微信扫一扫

JDK之ClassLoader加载过程与加载原理


文章目录

  • ​​1.官网​​
  • ​​2.整体流程​​
  • ​​2.1.Loading​​
  • ​​2.1.1.找到class所在的目录和文件​​
  • ​​2.1.1.1.JDK中有一个类叫ClassLoader.findClass(className),帮忙我们寻找和加载类​​
  • ​​2.1.1.2.不同的ClassLoader加载顺序图解​​
  • ​​2.1.2.2.1.双亲委派模式加载​​
  • ​​2.1.2.2.1.1.定义​​
  • ​​2.1.2.2.1.2.优势​​
  • ​​2.1.2.2.1.3.如何破坏这种模式​​
  • ​​2.1.2.将找到class文件加载到JVM中​​
  • ​​2.1.2.1.概述​​
  • ​​2.1.2.2.class文件在JVM中的存储分区问题介绍​​
  • ​​2.2.Linking​​
  • ​​2.2.1.Verification [验证]​​
  • ​​2.2.2.Preparation [准备]​​
  • ​​2.2.3.Resolution [解析]​​
  • ​​2.3.Initialization [初始化]​​


JDK之ClassLoader加载过程与加载原理_classloader加载原理

1.官网

​​https://docs.oracle.com/javase/specs/jvms/se8/html/index.html​​

JDK之ClassLoader加载过程与加载原理_栈_02


​​https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html​​

JDK之ClassLoader加载过程与加载原理_classloader加载原理_03

2.整体流程

2.1.Loading

2.1.1.找到class所在的目录和文件

2.1.1.1.JDK中有一个类叫ClassLoader.findClass(className),帮忙我们寻找和加载类

JDK之ClassLoader加载过程与加载原理_jd_04

2.1.1.2.不同的ClassLoader加载顺序图解

JDK之ClassLoader加载过程与加载原理_classloader加载过程_05

加载的顺序:加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。
从Custom ClassLoader到BootStrap ClassLoader逐层检查,
只要某个Classloader已加载,就视为已加载此类,保证此类只所有ClassLoader加载一次

2.1.2.2.1.双亲委派模式加载
2.1.2.2.1.1.定义

如果一个类加载器在接到加载类的请求时,它首先不会自己尝试去加载这个类,而是把
这个请求任务委托给父类加载器去完成,依次递归,如果父类加载器可以完成类加载任务,就
成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。

2.1.2.2.1.2.优势

Java类随着加载它的类加载器一起具备了一种带有优先级的层次关系。比如,Java中的
Object类,它存放在rt.jar之中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型
最顶端的启动类加载器进行加载,因此Object在各种类加载环境中都是同一个类。如果不采用
双亲委派模型,那么由各个类加载器自己取加载的话,那么系统中会存在多种不同的Object类。

通俗理解

比如不同的层级的classloader中有多个java.lang.Example.class类,这样会产生冲突;
这样先有上到下的去加载,其实就很好地避免了这个重复的问题

2.1.2.2.1.3.如何破坏这种模式

1.我们在ClassLoader.findClass(className)方法中,其实我们也可以看到,也是先去父加载器里面去加载
2.可以继承ClassLoader类,然后重写其中的loadClass方法,其他方式大家可以自己了解拓展一下。

JDK之ClassLoader加载过程与加载原理_classloader加载原理_06

2.1.2.将找到class文件加载到JVM中

2.1.2.1.概述

1.关于我们的class文件如何在JVM虚拟机中存储这一块,我们肯定不能全部直接放到JVM中,因为有一些东西是公用的,有一些东西跟我们每一次请求的
线程资源数据相关的,所以如何高效的利用存储JVM内存空间,就涉及到我们如何存储CLass文件
2.JVM对于class文件的存储时分块存储;
关于内存中的块,我们也可以参考官网的地址;

​​https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5​​

JDK之ClassLoader加载过程与加载原理_classloader加载过程_07

2.1.2.2.class文件在JVM中的存储分区问题介绍

2.2.Linking

​​https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4​​

JDK之ClassLoader加载过程与加载原理_jd_08

2.2.1.Verification [验证]

1.这里的验证主要是我们上面加载过来的class(二进制文件类或者接口)格式(structrue)的一个验证;
2.同时,会加载这个class依赖的其他的class(二进制文件类或者接口),这里注意下,这里不会验证这些加载进来的类的格式;

之所以不验证依赖的文件,主要是因为,我们每一个文件都会加载,所以没有必要再加载的时候,再次验证!

JDK之ClassLoader加载过程与加载原理_classloader加载原理_09

2.2.2.Preparation [准备]

1.为静态变量初始化内存空间
2.为静态变量初始化值
3.比如static int =10 这一行在初始化的时候,是初始化值为0

JDK之ClassLoader加载过程与加载原理_jd_10

2.2.3.Resolution [解析]

1.将符号引用转变为直接引用;

我们知道classFile的结构如下

1.下面的一些标示实际上只是一个符号引用,这里将符号引用指向为直接引用JVM内存中的实际地址;

ClassFile {
u4 magic; #文件类型
u2 minor_version; # jdk版本
u2 major_version; # jdk版本
u2 constant_pool_count; # 常量的个数
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class; #本类的引用
u2 super_class; #父类的引用
u2 interfaces_count;#接口数量
u2 interfaces[interfaces_count];
u2 fields_count; # 字段个属于
field_info fields[fields_count];
u2 methods_count; #方法个数
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}

下面是一个App.class的二进制文件(16进制)

cafe babe 0000 0034 001d 0a00 0600 0f09
0010 0011 0800 120a 0013 0014 0700 1507
0016 0100 063c 696e 6974 3e01 0003 2829
5601 0004 436f 6465 0100 0f4c 696e 654e
756d 6265 7254 6162 6c65 0100 046d 6169
6e01 0016 285b 4c6a 6176 612f 6c61 6e67
2f53 7472 696e 673b 2956 0100 0a53 6f75
7263 6546 696c 6501 0008 4170 702e 6a61
7661 0c00 0700 0807 0017 0c00 1800 1901
000c 4865 6c6c 6f20 576f 726c 6421 0700
1a0c 001b 001c 0100 1563 6f6d 2f67 616f
7869 6e66 752f 6465 6d6f 2f41 7070 0100
106a 6176 612f 6c61 6e67 2f4f 626a 6563
7401 0010 6a61 7661 2f6c 616e 672f 5379
7374 656d 0100 036f 7574 0100 154c 6a61
7661 2f69 6f2f 5072 696e 7453 7472 6561
6d3b 0100 136a 6176 612f 696f 2f50 7269
6e74 5374 7265 616d 0100 0770 7269 6e74
6c6e 0100 1528 4c6a 6176 612f 6c61 6e67
2f53 7472 696e 673b 2956 0021 0005 0006
0000 0000 0002 0001 0007 0008 0001 0009
0000 001d 0001 0001 0000 0005 2ab7 0001
b100 0000 0100 0a00 0000 0600 0100 0000
0700 0900 0b00 0c00 0100 0900 0000 2500
0200 0100 0000 09b2 0002 1203 b600 04b1
0000 0001 000a 0000 000a 0002 0000 000b
0008 000c 0001 000d 0000 0002 000e

2.3.Initialization [初始化]

1.为静态变量进行初始化赋值,比如:static int =10 开始设置值为10


举报

相关推荐

0 条评论