最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

双亲委派机制

来源:博客园

双亲委派机制

简单理解

简单一句话:我爸是李刚,有事找我爸。简单三个字:往上捅双亲委派就是,有啥事,先问问老爹,如果老爹不行,再问问爷爷,如果爷爷也没有,再告爸爸,爸爸再告诉诉儿子,你自己看着办吧。

图例


【资料图】

Java是运行在Java的虚拟机(JVM)中的,但是它是如何运行在JVM中了呢?我们在IDE中编写的Java源代码被编译器编译成.class的字节码文件。然后由我们得ClassLoader负责将这些class文件给加载到JVM中去执行。JVM中提供了三层的ClassLoader:

  • Bootstrap classLoader:主要负责加载核心的类库(java.lang.*等),构造ExtClassLoader和APPClassLoader。

  • ExtClassLoader:主要负责加载jre/lib/ext目录下的一些扩展的jar。

  • AppClassLoader:主要负责加载应用程序的主函数类

源码分析

打开IDEA,搜索ClassLoader,找到loadClass方法

protected Class loadClass(String name, boolean resolve)    throws ClassNotFoundException{    synchronized (getClassLoadingLock(name)) {        // First, check if the class has already been loaded        //先检测这个类是否以及被加载过        Class c = findLoadedClass(name);        if (c == null) { //如果没有被加载过            long t0 = System.nanoTime();            try {                // 存在父加载器,递归的交由父加载器                if (parent != null) { //检查父加载器是否加载过                    c = parent.loadClass(name, false);                } else {                    c = findBootstrapClassOrNull(name);                }            } catch (ClassNotFoundException e) {                // ClassNotFoundException thrown if class not found                // from the non-null parent class loader            }            if (c == null) {                /*在父类装入器上调用loadClass方法。如果父类为空,则使用虚拟机内置的类装入器。 调用findClass(String)方法来查找类。 如果使用上述步骤找到该类,并且resolve标志为true,则该方法将在结果class对象上调用resolveClass(class)方法。*/                //如果仍未找到,则按顺序调用findClass找到class                long t1 = System.nanoTime();                c = findClass(name);                // this is the defining class loader; record the stats                sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);                sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);                sun.misc.PerfCounter.getFindClasses().increment();            }        }        if (resolve) {             resolveClass(c);        }        return c;    }}

代码图例

双亲委派机制的好处

JVM为什么要使用双亲委派这种机制呢?有什么好处呢?通过我们自己写的java.lang.string这个类启动报错中,我们就可以得出以下双亲委派的优点:1、保证了JVM提供的核心类不被篡改,保证class执行安全比如上文的string类,无论哪个加载器要加载这个类的话,由于双亲委派机制,最终都会交由最顶层的启动类加载器来加载,这样保证了string类在各种类加载器环境中,都是同一个类。试想下,没有双亲委派机制的话,各个加载器自己加载string类,有可能不同类加载器加载的string方法不一样,那样的话,我们的程序是不是就会一片混乱了。

2、防止重复加载同一个class双亲委派机制流程图中,我们可以看出,委托向上问一问,如果加载过,就不用再加载了

总结:防止篡改,防止重复加载类

四种类加载机制的管辖范围

1、启动类加载器(BootstrapClassLoader):是由c++编写的,是JVM自身的一部分。用来加载Java核心类库的(java.*)的。构造ExtClassLoader和AppClassLoader的。需要注意的是:由于其是虚拟机自身的一部分,开发者是服务直接获取到启动类加载器的引用的,所以是不允许直接通过引用进行操作。

这个类加载器负责存放在\lib目录中的,或是被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的类库加载到虚拟机内存中

2、扩展类加载器(ExtensionClassLoader):Java语言编写的,加载扩展库。如classPath中的jre,javax.*(也即:\lib\ext目录中)或是java.ext.dir指定位置中的类。开发者可以直接使用这个扩展类加载器Java语言编写的,这个加载器是由sun.misc.Launcher$ExtClassLoader来实现的

3、应用程序类加载器(Application ClassLoader)这个类加载器是由sun.misc.Launcher#AppClassLoader实现的。由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值。所以也称为系统加载器。赋值加载用户类路径(ClassPath)上所指定的类库。

4、用户自定义类加载器(CustomClassLoader)Java语言编写的,用户自定义类加载器,可以加载指定路径的class文件

网上总结的脑图:

来源:https://img-blog.csdnimg.cn/2020121722082798.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NvZGV5YW5iYW8=,size_16,color_FFFFFF,t_70

关键词: 主要负责 重复加载 管辖范围