类加载器以及双亲委派机制

1、类加载器以及双亲委派机制

  

 

 

比如custom ClassLoader要加载一个类,会先询问它的parent类,然后AppClassLoader会看它有没有加载过这个类,如果没有继续询问它的parent即ExtensionClassLoader

直到询问至BootstrapClassLoader也没有加载,因为BootstrapClassLoader只负责加载核心类,所以加载失败。它的child即ExtensionClassLoader就会去尝试加载,但是这个类也不在它的加载

范围之内,也加载失败。最后就到了customlClassLoader这个加载器加载。(注意父类并不会主动调用子类去加载,而是父类加载失败后,子类再去尝试加载)。

 

双亲委派机制对于保证Java程序的稳定性起了十分重要的作用,在双亲委派机制下要加载一个类最终都会委派给顶端的BootstrapClassLoader进行加载,所以如果用户自己编写一个Java.lang.Object

类,并加载这个类并不会破坏程序的稳定性。

 

ClassLoader是这些类加载器的顶层父类,下面是其中加载源码:

  

 1 protected Class<?> loadClass(String name, boolean resolve)
 2         throws ClassNotFoundException
 3     {
 4         synchronized (getClassLoadingLock(name)) {
 5             // First, check if the class has already been loaded
 6             Class<?> c = findLoadedClass(name);
 7             if (c == null) {
 8                 long t0 = System.nanoTime();
 9                 try {
10                     if (parent != null) {
11                         c = parent.loadClass(name, false);
12                     } else {
13                         c = findBootstrapClassOrNull(name);
14                     }
15                 } catch (ClassNotFoundException e) {
16                     // ClassNotFoundException thrown if class not found
17                     // from the non-null parent class loader
18                 }
19 
20                 if (c == null) {
21                     // If still not found, then invoke findClass in order
22                     // to find the class.
23                     long t1 = System.nanoTime();
24                     c = findClass(name);
25 
26                     // this is the defining class loader; record the stats
27                     sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
28                     sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
29                     sun.misc.PerfCounter.getFindClasses().increment();
30                 }
31             }
32             if (resolve) {
33                 resolveClass(c);
34             }
35             return c;
36         }
37     }

 

由代码可以看出,加载类的时候会先自己找,没找到就找它的父加载器,父加载器也是如此,就类似于递归操作。如果没有找到合适的父加载器就调用 findClass 方法自己加载。

1    protected Class<?> findClass(String name) throws ClassNotFoundException {
2         throw new ClassNotFoundException(name);
3     }

进入findClass就直接抛出了ClassNotFoundException。但是像AppClassLoader等继承与URLClassLoader,而URLClassLoader的父类的父类就是ClassLoader,并重写了此方法。

所以如果想自定义类加载器,就只要继承ClassLoader然后重写这个方法就行。

 

 

posted @ 2020-09-18 21:49  zcr小翟  阅读(161)  评论(0编辑  收藏  举报