关于classLoader命名空间的问题

大家好 目前在看关于java虚拟机的书籍

书上说 个各类装载器都使用单独的命名空间 一个类型无法看到不在同一个命名空间装载的其它类型

书上还说 没个被加载到方法区的class类型都有一个常量区 常量区中存放着其他类型的名字 字段 方法

在jvm解析阶段 需要把常量区中的其它类型的符号引用指向正确的类型地址 而且在解析过程中使用当前类的classLoader的命名空间去搜索和加载其它类型 比如Cat类是被一个用户自定义的类加载器加载的,当虚拟机解析指向Mouse的引用时,会检查Mouse是否已经被Cat所属的命名空间加载 如果没有 就是用Cat的类加载器加载Mouse类 即使Mouse已经被加载到另一个命名空间中

于是我写了一个测试小程序

public class Test {

public static void main(String[] args) throws Exception{
    Object o = new Object();
    List<String> l = new ArrayList<String>();

    System.out.println(o.getClass().getClassLoader());
    System.out.println(l.getClass().getClassLoader());
    System.out.println(Test.class.getClassLoader());
}

}

为什么Test类使用的是AppClassLoader 而Object 和 List 还是使用的Bootstrap ClassLoader? 和上面的观点有矛盾啊

请大侠帮助解决 小弟谢谢了

BootStrapClassLoader :加载java运行过程中的核心类库JRE\lib\rt.jar, sunrsasign.jar, charsets.jar, jce.jar, jsse.jar, plugin.jar 以及存放在JRE\classes里的类

AppClassLoader :加载CLASSPATH变量指定路径下的类 即指你自已编写的类

所以Object和List会使用BootStrapClassLoader,因为它们是JDK提供的,而Test使用的是AppClassLoader,因为这是你自己编写的。

1:BootStrapClassLoader :加载java运行过程中的核心类库JRE\lib\rt.jar, sunrsasign.jar, charsets.jar, jce.jar, jsse.jar, plugin.jar 以及存放在JRE\classes里的类
2:ExtClassLoader :加载JRE\lib\ext 或者目录下的库文件目录下的类(包括任何子目录,有别于其他两个ClassLoader)
3:AppClassLoader :加载CLASSPATH变量指定路径下的类

A、其中AppClassLoader的parent(并非父类)为ExtClassLoader, ExtClassLoader的parent为BootStrapClassLoader,根据ClassLoader的委托模型,当要加载一个class时候会先让其parent来加载,如果parent找不到的话,再由自己来加载。
B、加载的第一个类的ClassLoader如果为BootStrapClassLoader的话,那么其他的所有类也必须又BootStrapClassLoader来加载,如果加载第一个类的ClassLoader为AppClassLoader的话,则类的加载按规则A来执行。

BootStrapClassLoader的默认Load路径可以通过 System.getProperty("sun.boot.class.path");来取得
ExtClassLoader的默认Load路径可以通过 System.getProperty("java.ext.dirs");来取得
AppClassLoader的默认Load路径可以通过 System.getProperty("java.class.path");来取得

其中ExtClassLoader,AppClassLoader的load可以通过命令:java -Djava.ext.dirs xxx xxx,java -Djava.class.path xxx xxx来改变
而BootStrapClassLoader的路径是用C++写死在JVM里面的,即使通过java -Dsun.boot.class.path xxx xxx来改变路径也不起任何作用。