自定义类加载器在复杂类加载情况下的运行分析
-
实例:
public class MyCat { public MyCat(){ System.out.println("MyCat is loaded by:"+this.getClass().getClassLoader()); } } public class MySample { public MySample() { System.out.println("MySample is loaded by :" +this.getClass().getClassLoader()); new MyCat(); //【重要】 } } public class MyTest17 { public static void main(String[] args) throws Exception { MyTest16 loader1 = new MyTest16("loader1"); Class<?> clazz = loader1.loadClass("Jvm.MySample"); //先加载 System.out.println("class : " + clazz.hashCode()); //如果注释掉该行,那么并不会实例化MySample对象,即MySample构造方法不会被调用 //因此不会实例化MyCat对象,即没有对Mycat进行主动使用,这里就不会加载MyCat Class ★ Object object = clazz.newInstance(); //再创建实例 } } (1)在注释掉★行的时候: 此时 Class<?> clazz = loader1.loadClass("Jvm.MySample"); 会加载MySample、MyCat,虽然在MySample的构造方法中有new Cat(),但是这两个类并没有被初始化。这里有一个预加载的概念以及该节下面最后一句的踪迹。 运行结果: class : 325040804 (2)在放开★行的时候: 运行结果: class : 325040804 MySample is loaded by :sun.misc.Launcher$AppClassLoader@18b4aac2 MyCat is loaded by:sun.misc.Launcher$AppClassLoader@18b4aac2
-
结果分析:
- class : 325040804 由clazz.hashCode()输出,说明类被加载
- 而下面两行,纯属是因为clazz.newInstance()实例化了方法,调用构造方法打印出来的,两个类是否被加载进一步分析—>
-
注释掉 Object object = clazz.newInstance();, VM options 配置上 -XX:+TraceClassLoading
- 看结果:(MyCat没有被加载!!!)
-
- **MyCat是否被加载,并不是取决于是否被主动使用!**这里可以回顾 “**主动加载**” 和 "**预加载**"。