JVM总结(1)
1.什么是双亲委派:
先来说说JVM里面有那些类加载器吧:
1.启动类加载器(BootClassLoader)
2.扩展类加载器(ExtClassLoader)
3.应用类加载器(AppClassLoader)
4.自定义类加载器
那么双亲委派是什么:
应用类加载器判断自己的空间下是否有该类,有则直接返回,没有的话就扩展类加载器,
扩展类加载器判断自己的空间下是否有该类,有则直接返回,没有的话就启动类加载器,
启动类加载器判断自己的空间下是否有该类,有则直接返回,再去调用一下应用类加载器的findClass(),没有的话就抛出异常。
为什么使用双亲委派:为了安全,这是为了保证如果加载的类是一个系统类,那么会优先由启动类加载器或扩展类加载器去加载,保证系统的安全。
这3种类加载器存在父子关系,即应用类加载器的父亲是扩展类加载器,扩展类加载器的父亲是启动类加载器,但是他们并不是继承关系。
当3种类加载器在加载类是,会先委托上层的类加载器进行加载,一直往上,称为向上委派,如果最顶级的父类加载器没有找到该类时,就会抛出异常。
在ClassLoader的抽象类中:
先去自己的类加载器里面查找,如果找不到,如果存在父类加载器,往父类加载器去查找,如果没有父类加载器就是到了启动类加载器查找了,如有即返回,没有的话再去调用一下应用类加载器的findClass(),没有的话就抛出异常。
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; } }
那么双亲委派的局限性是什么:它只能向上委派。
打破双亲委派:
1.不委派
2.向下委派。