一站式了解双亲委派机制



引言

当在简历上写上了解JVM的知识时,双亲委派机制这个知识点就有很大可能要被问,所以了解好这个知识点很重要。这个栏目也会继续讲其他JVM的常见知识点,感兴趣的同学可以关注一下❤️

什么是双亲委派机制😯

双亲委派机制是Java虚拟机(JVM)中的一种类加载机制,用于确保类的加载过程的安全性和一致性。其解决的核心问题是一个类到底是由谁来加载的问题。

简单点来说,就是类加载器要进行加载类任务时,首先会自底向上查找该类是否被加载过,再由顶向下进行加载。
自下向上查找是否有加载过就可以避免重复加载问题,加载过就直接返回。
如果该类没有加载过,就由最上方的加载器开始判定该类是否在加载目录中,如果不是就让下一个进行加载

双亲委派机制的作用😣

  • 保证类的唯一性:通过这种方式,可以确保在整个JVM中,同一个类只会被加载一次,避免了重复加载的问题。
  • 避免类的重复加载:由于类加载器会首先检查是否已经加载过某个类,这减少了内存消耗并提高了性能。
  • 安全性保证:核心API由启动类加载器加载,防止了用户自定义类对关键类的覆盖,从而提升了系统的安全性

三个类加载器😗

在Java中,默认有三种主要的类加载器:

  1. 启动类加载器(Bootstrap ClassLoader) :这是最顶层的类加载器,通常由本地代码实现(如C/C++),负责加载核心Java库中的类,比如rt.jar
  2. 扩展类加载器(Extension ClassLoader) :负责加载位于<JAVA_HOME>/lib/ext目录下的扩展库。
  3. 应用程序类加载器(Application ClassLoader) :也称为系统类加载器,负责加载用户类路径(ClassPath)下的所有类。

如果还有,就是用户自己实现的类加载器

用代码主动加载一个类😈

在Java中,有几种方法可以主动加载一个类。通常,类的加载是由JVM根据需要自动完成的,但有时你可能希望手动控制这个过程。下面是几种实现方式:

使用 Class.forName()

这是最常见的方式之一,通过Class.forName(String className)方法来加载指定名称的类。该方法会尝试使用当前线程的上下文类加载器来加载类。

try {
    Class<?> clazz = Class.forName("com.example.MyClass");
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

在这个例子中,"com.example.MyClass"是你想要加载的类的全限定名(即包括包名的类名)。如果找不到该类,则会抛出ClassNotFoundException

使用类加载器的 loadClass() 方法

你也可以直接调用类加载器的loadClass()方法来加载类。这允许你更精确地控制使用哪个类加载器进行加载。

ClassLoader classLoader = MyClass.class.getClassLoader();
try {
    Class<?> clazz = classLoader.loadClass("com.example.MyClass");
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

这里,我们首先获取了当前类(假设是MyClass)的类加载器,然后使用它来加载目标类。

打破双亲委派机制😫

在Java中,默认的类加载机制是基于双亲委派模型(Parent Delegation Model),它确保了类的安全性和唯一性。然而,在某些特定场景下,可能需要打破这种默认机制,以实现特定的功能需求,比如加载不同版本的库或者支持动态模块系统等

使用线程上下文类加载器

这是最常见的方式之一,特别是在Java的一些扩展框架中,如JNDI、JDBC等,它们使用线程上下文类加载器来加载服务提供者接口(SPI)的实现类。通过这种方式,可以绕过双亲委派模型,让应用程序类加载器或自定义类加载器加载所需的类。

ClassLoader original = Thread.currentThread().getContextClassLoader();
try {
    Thread.currentThread().setContextClassLoader(MyCustomClassLoader.class.getClassLoader());
    // 在这里执行需要使用MyCustomClassLoader加载的代码
} finally {
    // 恢复原始的上下文类加载器
    Thread.currentThread().setContextClassLoader(original);
}

自定义类加载器

创建一个自定义类加载器并重写loadClass()方法,可以直接控制类的加载过程,从而打破双亲委派机制。通常,你只需重写findClass()方法来指定如何查找和加载类文件,但如果需要完全控制类的加载顺序,则需重写loadClass()方法。

public class MyClassLoader extends ClassLoader {
    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        // 你可以在这里实现自己的逻辑来加载类,而不是首先委托给父类加载器
        return super.loadClass(name);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] classData = // ... 根据名字获取类的数据
        return defineClass(name, classData, 0, classData.length);
    }
}

总结❤️

这就是双亲委派机制的常见知识点了

如果你看了这篇文章有收获可以点赞+关注+收藏🤩,这是对笔者更新的最大鼓励!如果你有更多方案或者文章中有错漏之处,请在评论区提出帮助笔者勘误,祝你拿到更好的offer!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

想用offer打牌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值