类加器双亲委托机制
类加载器
Java当中类加载器的层次体系
- 根类加载器
- 扩展类加载器
- 系统类加载器
- 用户自定义类加载器
这是有最顶层根类加载器下面一层就是扩展类加载器依此类推。
用户自定义加载器一般都从系统类加载器衍生。
类加载器的父亲委托机制
- 在父类委托机制中,各个加载器按照父子关系形成了树形结构,除了根类加载器之外其余的加载器都有且只有一个父加载器。
- 若有一个类加载器能成功加载Test类,那么这个类加载器被称为定义类加载器,所有能成功成功返回Class对象应用的类加载器(包括定义类加载器)都被成为初始类加载器(了解)
如图:
**双亲委托机制:**loader1想要去加载Sample类,根据类加载器的双亲委托机制不是由loader1加载到Sample类当中,其实它是吧Sample类转交给系统类加载器然后在交给扩展类加载器发现他也有父亲,就会转交给根类加载器然而根类加载器并不能加载。
我们可以看看下面的图
**双亲委托机制:**这里说了根类不能加载失败了Sample类所以他就会返回扩展类加载器尝试加载依此类推,当加载成功就会吧结果返回给loader1
Bootstrap ClassLoader、Extension ClassLoader、App ClassLoader
- Bootstrap ClassLoader (根类加载器)
- $JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类
- Extension ClassLoader(扩展类加载器)
- 负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定吗目录下的jar包
- App ClassLoader (系统类加载器)
- 负责加载classpath中指定的jar包及目录中class
接下来我们用代码进行测试
public class MyTest7 {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> clazz= Class.forName("java.lang.String");
System.err.println(clazz.getClassLoader());
}
}
运行结果:
这里我们可以看一下.getClassLoader()的源代码定义在Class类当中以及一些英文注释后面都接上中文翻译大家都凭自己的理解
/**
* Returns the class loader for the class. Some implementations may use 返回类的类加载器。一些实现可能使用
* null to represent the bootstrap class loader. This method will return 空表示引导类装入器。此方法将返回
* null in such implementations if this class was loaded by the bootstrap 如果此类是由引导程序加载的,则在此类实现中为空
* class loader. 类加载器
*
* <p> If a security manager is present, and the caller's class loader is
* not null and the caller's class loader is not the same as or an ancestor of 如果存在安全管理器,并且调用方的类加载器是
* the class loader for the class whose class loader is requested, then 请求其类加载器的类的类加载器,然后
* this method calls the security manager's {@code checkPermission} 此方法调用安全管理器的{@code checkPermission}
* method with a {@code RuntimePermission("getClassLoader")} 具有{@code RuntimePermission(“getClassLoader”)的方法
* permission to ensure it's ok to access the class loader for the class. 权限,以确保可以访问该类的类加载器。
*
* <p>If this object 如果这个对象
* represents a primitive type or void, null is returned. 表示基元类型或void,返回null。
*
* @return the class loader that loaded the class or interface 加载类或接口的类加载器
* represented by this object. 由这个对象表示。
* @throws SecurityException
* if a security manager exists and its 如果存在安全管理器及其
* {@code checkPermission} method denies {@code checkPermission}方法拒绝
* access to the class loader for the class. 访问类的类加载器。
* @see java.lang.ClassLoader
* @see SecurityManager#checkPermission
* @see java.lang.RuntimePermission
*/
@CallerSensitive
public ClassLoader getClassLoader() {
ClassLoader cl = getClassLoader0();
if (cl == null)
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass());
}
return cl;
}
这里的clazz输出为null所以是有Bootstrap ClassLoader(根类加载器)$JAVA_HOME中jre/lib/rt.jar里所有的class因为String是rt.jar里面的class文件,大家可以看看这句翻译(null in such implementations if this class was loaded by the bootstrap 如果此类是由引导程序加载的,则在此类实现中为空)
更改代码进行测试
public class MyTest7 {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> clazz= Class.forName("java.lang.String");
System.err.println(clazz.getClassLoader());
Class<?> clazz2= Class.forName("com.jvm.classloader.A");
System.err.println(clazz2.getClassLoader());//获取类加载器
}
}
class A {
}
运行结果:
那么clazz2的输出sun.misc.Launcher$AppClassLoader@73d16e93,AppClassLoader(应用类加载器)系统类加载器这里证明了A的加载器是AppClassLoader接下来我们来看看这个类里面的代码。
static class AppClassLoader extends java.net.URLClassLoader {
final sun.misc.URLClassPath ucp;
public static java.lang.ClassLoader getAppClassLoader(java.lang.ClassLoader classLoader) throws java.io.IOException { /* compiled code */ }
AppClassLoader(java.net.URL[] urls, java.lang.ClassLoader classLoader) { /* compiled code */ }
public java.lang.Class<?> loadClass(java.lang.String s, boolean b) throws java.lang.ClassNotFoundException { /* compiled code */ }
protected java.security.PermissionCollection getPermissions(java.security.CodeSource codeSource) { /* compiled code */ }
private void appendToClassPathForInstrumentation(java.lang.String s) { /* compiled code */ }
private static java.security.AccessControlContext getContext(java.io.File[] files) throws java.net.MalformedURLException { /* compiled code */ }
}
java.security.AccessControlContext getContext(java.io.File[] files) throws java.net.MalformedURLException { /* compiled code */ }
}
这里的是反编译出来的不是源代码AppClassLoader是我们的应用类加载器(系统类加载器)主要负责我们工程当中的class文件,他是间接从ClassLoader衍生展开的。