选择显示字体大小

classloader介绍

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());
}
}


1、我们将它放在classpath中,则打印出
sun.misc.launcher$appclassloader@92e78c
sun.misc.launcher$appclassloader@92e78c
可见都是由appclassloader来加载的。
2、我们将其放在%jre%/lib/ext/classes(即extclassloader的加载目录。其加载/lib/ext中的jar文件或者子目录classes中的class文件)中。则会打印出:
sun.misc.launcher$extclassloader
sun.misc.launcher$extclassloader
3、我们将a.class放到%jre%/lib/ext/classes中,而将b.class放到classpaht中又会怎么样呢?结果是:
sun.misc.launcher$extclassloader
exception in thread "main" java.lang.noclassdeffounderror:b
at a.main(a.java:6)

怎么会这样呢?这其中有一个重要的问题:a类当然是由extclassloader来加载的,b类要由哪个加载呢?b类要由调用它自己的类的类加载器(真拗口)。也就是说,a调用了b,所以b由a的类加载器extclassloader来加载。extclassloader根据委托机制,先拜托bootstrap加载,bootstrap没有找到。然后它再自己寻找b类,还是没找到,所以抛出异常。extclassloader不会请求appclassloader来加载!你可能会想:这算什么问题,我把两个类放到一起不就行了?

呵呵,没这么简单。比如jdbc是核心类库,而各个数据库的jdbc驱动则是扩展类库或在classpath中定义的。所以jdbc由bootstrap classloader加载,而驱动要由appclassloader加载。等等,问题来了,bootstrap不会请求appclassloader加载类啊。那么,他们怎么实现的呢?我就涉及到一个context classloader的问题,调用thread.getcontextclassloader。具体我还没搞太明白,要知后事如何,请听下回分解!(啊!别拿砖头砸我...)
from-javaresearch.org


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

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   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons