Java类加载器-面试必备!!

啊啊啊 不想学习 那就来写一篇博文吧┭┮﹏┭┮
有没有听说过Java的类加载器呢??

在了解Java类加载器之前,你是否知道类加载机制呢?

1.初识类加载过程

  • 首先在桌面上创建一个txt文件,里面写上一段正确的java代码,保存
    在这里插入图片描述

  • 接下来,将.txt文件命名为.java文件
    在这里插入图片描述

  • cmd下打开文件所在位置 执行命令javac

javac ceshi.java //进行编译,生成.class文件

  • 在执行命令java

java ceshi //类加载过程

在这里插入图片描述
在进行java ceshi时,就是进行类加载的过程,也就是把生成的字节码文件装载到java虚拟机(JVM)中。

2.类加载机制

当你编写了一段代码后,需要用JVM对其进行加载。JVM对java类的加载流程:

  • 将Java文件编译生成字节码文件
  • 类加载器读取字节码文件,并转换成java.lang.Class对象
  • 有了该Class对象,JVM利用反射的方法创建对象实例

Java提供了许多不同的类加载器,他们用来加载不同的文件。绝大多数继承于ClassLoader类。

问题来了:这些可爱的类加载器,它们怎么知道自己加载的文件是不是字节码文件呢??

这就需要我们来了解一下字节码文件
执行命令javap -verbose ceshi
在这里插入图片描述
下面是显示的结果:

C:\Users\admin\Desktop>javap -verbose ceshi
Classfile /C:/Users/admin/Desktop/ceshi.class
Last modified 2021-5-10; size 415 bytes
MD5 checksum 1c50e1ae93498831a1acd435817d8ed4
Compiled from “ceshi.java”
public class ceshi
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #6.#15 // java/lang/Object.""😦)V
#2 = Fieldref #16.#17 // java/lang/System.out:Ljava/io/PrintStream;
#3 = String #18 // hello,world
#4 = Methodref #19.#20 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Class #21 // ceshi
#6 = Class #22 // java/lang/Object
#7 = Utf8
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 main
#12 = Utf8 ([Ljava/lang/String;)V
#13 = Utf8 SourceFile
#14 = Utf8 ceshi.java
#15 = NameAndType #7:#8 // “”😦)V
#16 = Class #23 // java/lang/System
#17 = NameAndType #24:#25 // out:Ljava/io/PrintStream;
#18 = Utf8 hello,world
#19 = Class #26 // java/io/PrintStream
#20 = NameAndType #27:#28 // println:(Ljava/lang/String;)V
#21 = Utf8 ceshi
#22 = Utf8 java/lang/Object
#23 = Utf8 java/lang/System
#24 = Utf8 out
#25 = Utf8 Ljava/io/PrintStream;
#26 = Utf8 java/io/PrintStream
#27 = Utf8 println
#28 = Utf8 (Ljava/lang/String;)V
{
public ceshi();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object.""😦)V
4: return
LineNumberTable:
line 1: 0

public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String hello,world
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 3: 0
line 4: 8
}
SourceFile: “ceshi.java”

以上就是字节码一个简单的字节码文件的全部内容了,我们来看看第四行:

MD5 checksum 1c50e1ae93498831a1acd435817d8ed4

有没有听说过魔数??字节码文件的前四个字节,我们称之为魔数。它的作用,就是来告诉类加载器:黑,我是一个字节码文件,你可以放心加载我了。而MD5,就是用来对魔数进行加密,加密的结果,就是MD5 checksum后面跟着的一长串令人头疼的字符。

好家伙,问题又来了,识别出一个文件是字节码文件了,那么有这么多类加载器,由哪一种类加载器对这个字节码文件进行加载呢?

这就需要来了解类加载器了。

3.类加载器

主要介绍三种类加载器:Bootstrap ClassLoader (启动类加载器)、Ext ClassLoader(扩展类加载器)、App ClassLoader(应用类加载器)

(1)Bootstrap ClassLoader(启动类加载器|根加载器|引导类加载器)
  • 用来加载JAVA_HOME/jre/lib里的jar包(该目录下所有jar包是运行JVM时所必需的jar包)
  • 类加载器本身也是类,需要有其他类加载器对其进行加载,Bootstrap ClassLoader就是他们的老大(类加载器的顶级父类)。
  • Bootstrap ClassLoader是由C语言进行开发的。
  • 如果一个类的类加载器是Bootstrap ClassLoader,那么该类的getClassLoader()方法返回null
    在这里插入图片描述在这里插入图片描述
    看来String类是由Bootstrap ClassLoader进行加载的(●’◡’●)
    ps:如果你不知道你的JAVA_HOME的位置,你可以在cmd下输入
    echo %JAVA_HOME%
    进行查看
(2)扩展类加载器(Ext ClassLoader)
  • 主要加载JAVA_HOME/jre/ext下的jar包
(3)应用类加载器(App ClassLoader)
  • 主要加载用户自己编写的类,也就是CLASSPATH下的所有jar文件

4.双亲委派模型

说实话,我一直对双亲委派模型有一种朦胧的感觉,我怕我说错,就不说了(百度会搜到很多解释)。我来说一下双亲委派模型的好处(●’◡’●)
(1)安全性。可以避免用户自定义的类动态替换java的一些核心类,保证了安全。
(2)避免类的重复加载。JVM判断两个类是否是同一个类,不仅根据类名判断,还根据加载这个类的类加载器是否相同进行判断。用两种类加载器去加载同一个类,得到的就是两个不同的类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值