jvm在运行时会产生三个classloader,bootstrap classloader、extension classloader和appclassloader.其中,bootstrap是用c++编写的,我们在java中看不到它,是null。它用来加载核心类库,在jvm源代码中这样写道:
static const char classpathformat[] =
"%/lib/rt.jar:"
"%/lib/i18n.jar:"
"%/lib/sunrsasign.jar:"
"%/lib/jsse.jar:"
"%/lib/jce.jar:"
"%/lib/charsets.jar:"
"%/classes";
知道为什么不需要在classpath中加载这些类了吧?人家在jvm启动的时候就自动加载了,并且在运行过程中根本不能修改bootstrap加载路径。
extension classloader用来加载扩展类,即/lib/ext中的类。
最后appclassloader才是加载classpath的。
classloader加载类用的是委托模型。即先让parent类(而不是super,不是继承关系)寻找,parent找不到才自己找。看来classloader还是蛮孝顺的。三者的关系为:appclassloader的parent是extclassloader,而extclassloader的parent为bootstrap classloader。加载一个类时,首先bootstrap先进行寻找,找不到再由extclassloader寻找,最后才是appclassloader。
为什么要设计的这么复杂呢?其中一个重要原因就是安全性。比如在applet中,如果编写了一个java.lang.string类并具有破坏性。假如不采用这种委托机制,就会将这个具有破坏性的string加载到了用户机器上,导致破坏用户安全。但采用这种委托机制则不会出现这种情况。因为要加载java.lang.string类时,系统最终会由bootstrap进行加载,这个具有破坏性的string永远没有机会加载。
我们来看这段代码:
//a.java
public class a{
public static void main(string[] args){
a a=new a();
system.out.println(system.getproperty("java.ext.dirs"));
system.out.println(a.getclass().getclassloader());
b b=new b();
b.print();
}
}
//b.java
public class b{
public void print(){
system.out.println(this.getclass().getclassloader());
}
}
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器