java类加载 双亲委派机制

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shy415502155/article/details/88167713

为什么需要双亲委派模型呢?

自定义一个java.lang.String类,该String类具有系统的String类一样的功能,只是在某个函数稍作修改。比如equals函数,这个函数经常使用,如果在这这个函数中加入一些“病毒代码”。并且通过自定义类加载器加入到JVM中。此时,如果没有双亲委派模型,那么JVM就可能误以为自定义的java.lang.String类是系统的String类,导致“病毒代码”被执行。 

有了双亲委派模型,自定义的java.lang.String类永远都不会被加载进内存 

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

java中自带三个类加载器

1.启动类加载器(Bootstrap ClassLoader):由C++语言实现(针对HotSpot),负责将存放在<JAVA_HOME>\lib目录或-Xbootclasspath参数指定的路径中的类库加载到内存中。

2.其他类加载器:由Java语言实现,继承自抽象类ClassLoader。

      ①扩展类加载器(Extension ClassLoader):负责加载<JAVA_HOME>\lib\ext目录或java.ext.dirs系统变量指定的路径中的所有类库。
      ②应用程序类加载器(Application ClassLoader)。负责加载用户类路径(classpath)上的指定类库,我们可以直接使用这个类加载器。一般情况,如果我们没有自定义类加载器默认就是用这个加载器。

双亲委派机制

在java.lang.ClassLoader类中loadClass方法

private final ClassLoader parent;
public Class<?> loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);
    }

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) {
                    // If still not found, then invoke findClass in order
                    // to find the 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;
        }
    }
protected Class<?> findClass(String name) throws ClassNotFoundException {
        throw new ClassNotFoundException(name);
    }

首先会调用自身的findLoadedClass()去内存中寻找这个类,通过AppClassLoader如果找不到则会调用其父类加载器 即ExtClassLoader同样去内存中寻找,如果找不到则会再通过父类加载器即BootStrap来寻找,

如果都没有找到则会一层一层返回,即BootStrap通过它自身定义的加载路径加载,如果加载不到则会通过ExtClassLoader

根据自身定义的加载路径加载,如果加载不到则会通过AppClassLoader加载。一直到最底层,如果没有任何加载器能加载,就会抛出ClassNotFoundException

猜你喜欢

转载自blog.csdn.net/shy415502155/article/details/88167713