类加载器你不知道的东西

程序员小迷 2024-06-10 14:46:09

类加载:通过一个类的全限定名来获取描述此类的二进制字节流,将二进制流加载到内存中,并转换为可执行的Java字节码。

一、双亲委派模型

概念:如果一个类加载器收到一个类加载的请求,它首先不会自己加载,而是把这个请求委派给父类加载器。只有父类无法完成加载时子类才会尝试加载。这就叫做双亲委派模型。

不同的加载器可以加载同名但不同版本的类,从而避免类冲突。

类加载器可以加载类文件、图片、配置文件等。

除顶层启动类加载器之外,其他都有自己的父类加载器。

//获取一个类的类加载器

Class.getClassLoader()

//获取一个类加载器的父类加载器

ClassLoader.getParent()

从 Java 虚拟机角度讲,只存在2种类加载器:

1.启动类加载器(C++ 实现,是虚拟机的一部分)。

2.其他所有的类的加载器(Java实现,独立于虚拟机外部且继承自java.lang.ClassLoader)。

从类加载器继承角度讲,存在如下4种类加载器:

1.启动类加载器(Bootstrap ClassLoader,也称根类加载器)

加载 $JAVA_HOME/jre/lib 下或 -Xbootclasspath 路径下的类。

2.扩展类加载器(Extension ClassLoader)

加载 $JAVA_HOME/jre/lib/ext 或 java.ext.dirs 系统变量所指定的路径下的类。

此类加载器以启动类加载器为父加载器。

3.应用程序类加载器(Application ClassLoader,也称系统类加载器)

负责加载用户路径下所指定的类库。

此类加载器以扩展类加载器为父加载器。

4.自定义类加载器

自定义类加载器(继承自java.lang.ClassLoader)可以实现类的动态加载、动态更新以及热部署等高级特性。

可通过继承java.lang.ClassLoader类并重写findClass来实现自定义的类加载逻辑。

二、破坏双亲委派模型

1.ClassLoader.loadClass()方法破坏了双亲委派模型,更推荐使用ClassLoader.findClass()方法来实现符合双亲委派模型的类加载逻辑。

2.线程上下文类加载器(Thread Context ClassLoader)

JNDI(Java Naming and Directory Interface)使用线程上下文类加载器去加载所需的SPI(Service Provider Interface)代码。这使父类加载器请求子类加载器完成类加载的行为,破坏了双亲委派模型的结构。

3.OSGi(Open Service Gateway initiative)实现模块化热部署时,采用了自定义的类加载器机制,这破坏了双亲委派模型。

三、引申

类加载器不需要等到某个类被"首次主动使用"时才加载它,JVM 规范允许类加载器在预测到某个类将要被使用时就提前预先加载它。如果在预先加载的过程中遇到了.class 文件缺失错误,类加载器必须在程序首次主动使用该类时抛出错误(LinkageError 错误)。如果这个类一直没有被程序主动使用,那么类加载器就不会抛出错误。

微风不燥,阳光正好,你就像风一样经过这里,愿你停留的片刻温暖舒心。

我是程序员小迷(致力于C、C++、Java、Kotlin、Android、Shell、JavaScript、TypeScript、Python等编程技术的技巧经验分享),若作品对您有帮助,请关注、分享、点赞、收藏、在看、喜欢,您的支持是我们为您提供帮助的最大动力。

欢迎关注。助您在编程路上越走越好!

0 阅读:15

程序员小迷

简介:致力于Android、iOS、C、Java等编程技术的技巧经验分享