标签:been public sync nan list string throw 委托 方法
1 public Class<?> loadClass(String name) throws ClassNotFoundException { 2 return loadClass(name, false); 3 } 4 5 protected Class<?> loadClass(String name, boolean resolve) 6 throws ClassNotFoundException 7 { 8 synchronized (getClassLoadingLock(name)) { 9 // First, check if the class has already been loaded 10 Class<?> c = findLoadedClass(name); 11 if (c == null) { 12 long t0 = System.nanoTime(); 13 try { 14 if (parent != null) { 15 c = parent.loadClass(name, false); 16 } else { 17 c = findBootstrapClassOrNull(name); 18 } 19 } catch (ClassNotFoundException e) { 20 // ClassNotFoundException thrown if class not found 21 // from the non-null parent class loader 22 } 23 24 if (c == null) { 25 // If still not found, then invoke findClass in order 26 // to find the class. 27 long t1 = System.nanoTime(); 28 c = findClass(name); 29 30 // this is the defining class loader; record the stats 31 sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); 32 sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); 33 sun.misc.PerfCounter.getFindClasses().increment(); 34 } 35 } 36 if (resolve) { 37 resolveClass(c); 38 } 39 return c; 40 } 41 }
从源码(jdk1.8)中看loadClass这个方法,注释上已经说的很清楚了,调用findLoadedClass方法检查有没有加载过这个类,如果没有就调用parent的loadClass方法,从底层一级级往上。如果找到最后都没有ClassLoader加载过这个类,就调用findClass方法查找这个类,然后又从顶层一级级往下调用findClass方法,如果有自定义ClassLoader的话最后会走到自定义的findClass方法,最终都没找到就抛出ClassNotFoundException。
比如两个类A和类B都要加载System类:
如果不用委托而是自己加载自己的,那么类A就会加载一份System字节码,然后类B又会加载一份System字节码,这样内存中就出现了两份System字节码。
如果使用委托机制,会递归的向父类查找,也就是首选用Bootstrap尝试加载,如果找不到再向下。这里的System就能在Bootstrap中找到然后加载,如果此时类B也要加载System,也从Bootstrap开始,此时Bootstrap发现已经加载过了System那么直接返回内存中的System即可而不需要重新加载,这样内存中就只有一份System的字节码了。
如果有人想篡改System类,如String.java,在这种机制下这些系统的类已经被Bootstrap classLoader加载过了,就算自己重写,也总是使用Java系统提供的System,自己写的System类根本没有机会得到加载。从一定程度上防止了危险代码的植入。
标签:been public sync nan list string throw 委托 方法
原文地址:https://www.cnblogs.com/bce1100/p/10579081.html