问题描述
大家好 目前在看关于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运行过程中的核心类库JRElibrt.jar, sunrsasign.jar, charsets.jar, jce.jar, jsse.jar, plugin.jar 以及存放在JREclasses里的类AppClassLoader :加载CLASSPATH变量指定路径下的类 即指你自已编写的类所以Object和List会使用BootStrapClassLoader,因为它们是JDK提供的,而Test使用的是AppClassLoader,因为这是你自己编写的。1:BootStrapClassLoader :加载java运行过程中的核心类库JRElibrt.jar, sunrsasign.jar, charsets.jar, jce.jar, jsse.jar, plugin.jar 以及存放在JREclasses里的类2:ExtClassLoader :加载JRElibext 或者目录下的库文件目录下的类(包括任何子目录,有别于其他两个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来改变路径也不起任何作用。