结论:类的双亲委托机制:
1. java 虚拟机中存在的类加载器:
根类加载器:加载jre/lib/rt.jar 或者 -Xbootclasspath 选项指定的jar 包
扩展类加载器:加载jre/lib/ext/*.jar 或者 -Djava.ext.dirs 指定目录下的jar包
应用(系统)类加载器:加载classpath 或者 -Djava.class.path 指定目录下的类和jar包,通常一个项目中编写的类通常打包到classpath 下,然后由系统类进行加载的
2. java 虚拟机进行类的加载,是自下而上,依次先将加载的类由应用类加载器传递给扩展类加载器,然后由其委托给根类加载器进行加载,然后再由上而下,依据其自身加的的类路径和指定参数进行加载,如果加载成功则返回,如果没加载不了就会返回给委托它的子类进行加载。
3. 调用ClassLoader.loadClass() 方法不会导致类的初始化,而通过反射class.forName()才会导致该类的初始化(通过反射操作类时,会导该类的初始化)
/**
* 结论:类的双亲委托机制:
* 1. java 虚拟机中存在的类加载器:
* 根类加载器:加载jre/lib/rt.jar 或者 -Xbootclasspath 选项指定的jar 包
* 扩展类加载器:加载jre/lib/ext/*.jar 或者 -Djava.ext.dirs 指定目录下的jar包
* 应用(系统)类加载器:加载classpath 或者 -Djava.class.path 指定目录下的类和jar 包,通常一个项目中编写的类通常打包到classpath 下,然后由系统类进行加载的
* 2. java 虚拟机进行类的加载,是自下而上,依次先将加载的类由应用类加载器传递给扩展类加载器,然后由其委托给根类加载器进行加载,然后再由上而下,依据其自身加的的类
* 路径和指定参数进行加载,如果加载成功则返回,如果没加载不了就会返回给委托它的子类进行加载。
* 3. 调用ClassLoader.loadClass() 方法不会导致类的初始化,而通过反射class.forName()才会导致该类的初始化(通过反射操作类时,会导该类的初始化)
*
*
*/
public class ClassLoaderTest1 {
public static void main(String[] args) throws ClassNotFoundException{
Class cls = Class.forName("java.lang.String");
System.out.println(cls.getClassLoader());//结果是 null ,说明是根加载器进行加载的,因为该类位于rt.jar 包中
System.out.println(ClassLoaderTest1.class.getClassLoader());// 结果是sum.misc.Launcher$AppClassLoader ,说明是应用类加载器进行加载的
System.out.println("---------------------------");
System.out.println(ClassLoaderTest1.class.getClassLoader().loadClass("com.tanruyu.jvm.classloading.TestClassLoader"));
System.out.println("________________________________");
System.out.println(Class.forName("com.tanruyu.jvm.classloading.TestClassLoader"));
}
}
class TestClassLoader {
static {
System.out.println("TestClassLoader init");
}
}