类加载器、双亲委派机制是干啥的?一文详解
目录一.类加载器1.作用加载class文件举例2.过程详解代码示例3.类加载器的种类①启动类根加载器(Bootstrap ClassLoader爷爷)②扩展类加载器(Extension ClassLoader爸爸)③应用程序加载器(Application ClassLoader儿子)举例二.双亲委派机制1.目的为了保证 Java 核心类库的安全防止它们被恶意篡改2.“双亲委派”的含义3.代码举例故意篡改String类看看是否生效4.代码举例我们自定义一个Student类肯定就随便了一.类加载器1.作用加载class文件举例new Student()这在做什么事情创建了一个Student类的具体实例对象引用变量名放在了栈而具体的对象放在了堆。2.过程详解类加载器负责下图的Car.class这个类文件加载成Car这个类然后就可以根据这个类创建具体的实例了过程如下代码示例//类是模板对象是实例 Car car1 new Car(); Car car2 new Car(); System.out.println(car1 car2); //获取这两个对象的类模版 Class? extends Car class1 car1.getClass(); Class? extends Car class2 car2.getClass(); System.out.println(class1 class2);运行结果可见两个对象的类模板是同一个。这也是一句废话因为创建的时候就是根据同一个类new的实例再倒回去肯定也是同一个类3.类加载器的种类类加载器其实也不像大家想的那么简单它其实也分成很多种类。而且他们之间有层级关系如下图①启动类根加载器(Bootstrap ClassLoader爷爷)②扩展类加载器(Extension ClassLoader爸爸)③应用程序加载器(Application ClassLoader儿子)举例//类是模板对象是实例 Car car1 new Car(); //获取这个对象的类模版 Class? extends Car class1 car1.getClass(); System.out.println(儿子:class1.getClassLoader()); System.out.println(爸爸:class1.getClassLoader().getParent()); System.out.println(爷爷:class1.getClassLoader().getParent().getParent());运行结果解读可见此时儿子就是“AppClassLoader”即应用程序加载器父亲是“PlatformClassLoader”我用的JDK17给这个加载器改名了JDK8叫ExtClassLoader即扩展类加载器爷爷是null即启动类加载器因为启动类加载器它是用 C 写的不是 Java 写的故获取不到因此用null代表它二.双亲委派机制1.目的为了保证Java 核心类库的安全防止它们被恶意篡改2.“双亲委派”的含义①先声明这是翻译时候出了错误正确的情况下应该叫“父亲委派”。②双亲委派机制的过程描述当一个类加载器收到类的加载请求时它不会自己动手而是先将请求向上委派给它的父加载器这个委派过程会一直持续到最顶层的启动类加载器只有当父加载器在自己的加载范围内找不到这个类时请求才会原路返回由下一级加载器尝试自己加载如果所有加载器都找不到最终才会抛出异常。3.代码举例故意篡改String类看看是否生效如下图我们自己伪造了一个String类并在该类中定义了一个main方法。但是运行以后发现程序报错“在java.lang.String中找不到main方法”。思考我们自己明明定义了main方法为什么偏偏报错说找不到呢答案①从人情角度讲String可是Java官方核心类库里面的东西最权威了岂是你说改就改的所以肯定是不允洗你瞎改的这很合理。②从“双亲委派机制”的角度讲一下原理JVM 需要加载java.lang.String这个类但“应用程序加载器”自己先不加载而是不断向上交给父加载器去处理双亲委派机制。根据双亲委派加载的请求最终一步步交给了启动类加载器Bootstrap ClassLoader是最顶层的类加载器。启动类加载器在rt.jarJDK 核心库里找到了官方的String类于是会进行加载操作。结果JVM 加载并使用的是官方的 String而不是你写的这个而人家官方的String类里面可是没有main方法的因此就会报错找不到。综上可体现出双亲委派机制本质上就是为了构建一道安全防线确保 Java 的核心类库不被随意篡改。说白了就是当你想篡改核心类库的东西的时候你的应用程序加载器等级太低不配先加载你自定义的假官方类而是要遵循“双亲委派机制”向上一步步交给“启动类加载器”先加载而启动类加载器里面就有核心类库的所有类因此会加载。而你折腾半天人家理都不理直接越过了。可见这个机制确实安全。4.代码举例我们自定义一个Student类肯定就随便了因为Student类是啥东西我们自定义的也不属于Java核心类库的东西人家也用不着保护。所以应用程序加载器根据双亲委派机制一步步上报到启动类加载器时人家没有然后往回退扩展类加载器也没有该类结果最终回退到应用程序加载器于是我们自己写的Student类就被加载了。本质原因就是自定义的Student类不属于核心类库才让应用程序加载器有机会加载不然会被它的父加载器拦截。以上就是本篇文章的全部内容喜欢的话可以留个免费的关注呦~~~