首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 企业软件 > 行业软件 >

Java类加载器引见

2013-05-02 
Java类加载器介绍如果应用程序类加载器需要加载一个类,它首先委托扩展类加载器,扩展类加载器再委托引导类

Java类加载器介绍

如果应用程序类加载器需要加载一个类,它首先委托扩展类加载器,扩展类加载器再委托引导类加载器。如果父类加载器不能加载类,子类加载器就回在自己的库中查找这个类。基于这个特性,类加载器只负责它的祖先无法加载的类。

如 果类加载器加载一个类,这个类不是在类加载器树上的叶子节点上,就会出现一些有趣的问题。比如例12-1,一个名为WhichClassLoader1 的类加载了一个名为WhichClassLoader2类,WhichClassLoader2又调用了名为WhichClassLoader3的类。

例12-1 WhichClassLoader1 和 WhichClassLoader2 源代码

public class WhichClassLoader1 {

public static void main(String[] args) throws javax.naming.NamingException

{

// Get classpath values

String bootClassPath = System.getProperty("sun.boot.class.path");

String extClassPath = System.getProperty("java.ext.dirs");

String appClassPath = System.getProperty("java.class.path");

// Print them out

System.out.println("Bootstrap classpath =" + bootClassPath + "/n");

System.out.println("Extensions classpath =" + extClassPath + "/n");

System.out.println("Application classpath=" + appClassPath + "/n");

// Load classes

Object bj = new Object();

WhichClassLoader1 wcl1 = new WhichClassLoader1();

WhichClassLoader2 wcl2 = new WhichClassLoader2();

// Who loaded what?

System.out.println("Object was loaded by "

+ obj.getClass().getClassLoader());

System.out.println("WCL1 was loaded by "

+ wcl1.getClass().getClassLoader());

System.out.println("WCL2 was loaded by "

+ wcl2.getClass().getClassLoader());

wcl2.getTheClass();

}

}

======================================================================

public class WhichClassLoader2 {

// This method is invoked from WhichClassLoader1

public void getTheClass() {

WhichClassLoader3 wcl3 = new WhichClassLoader3();

System.out.println("WCL3 was loaded by "

+ wcl3.getClass().getClassLoader());

}

}

如 果所有的WhichClassLoaderX 类都放在应用程序的类路径下,三个类就会被应用程序类加载器加载,这个例子就会运行正常。现在假定把WhichClassLoader2 类文件打包成JAR文件放在<JAVA_HOME>/jre/lib/ext 目录下,运行WhichClassLoader1,就会看到例12-2的输出:

例12-2 NoClassDefFoundError? 异常跟踪

Bootstrap classpath

=C:/WebSphere/AppServer/java/jre/lib/vm.jar;C:/WebSphere/AppServer/java/jre/lib

/core.jar;C:/WebSphere/AppServer/java/jre/lib/charsets.jar;C:/WebSphere/AppServ

er/java/jre/lib/graphics.jar;C:/WebSphere/AppServer/java/jre/lib/security.jar;C

:/WebSphere/AppServer/java/jre/lib/ibmpkcs.jar;C:/WebSphere/AppServer/java/jre/

lib/ibmorb.jar;C:/WebSphere/AppServer/java/jre/lib/ibmcfw.jar;C:/WebSphere/AppS

erver/java/jre/lib/ibmorbapi.jar;C:/WebSphere/AppServer/java/jre/lib/ibmjcefw.j

ar;C:/WebSphere/AppServer/java/jre/lib/ibmjgssprovider.jar;C:/WebSphere/AppServ

er/java/jre/lib/ibmjsseprovider2.jar;C:/WebSphere/AppServer/java/jre/lib/ibmjaa

slm.jar;C:/WebSphere/AppServer/java/jre/lib/ibmjaasactivelm.jar;C:/WebSphere/Ap

pServer/java/jre/lib/ibmcertpathprovider.jar;C:/WebSphere/AppServer/java/jre/li

b/server.jar;C:/WebSphere/AppServer/java/jre/lib/xml.jar

Extensions classpath =C:/WebSphere/AppServer/java/jre/lib/ext

Application classpath=.

Exception in thread "main" java.lang.NoClassDefFoundError: WhichClassLoader3

at java.lang.J9VMInternals.verifyImpl(Native Method)

at java.lang.J9VMInternals.verify(J9VMInternals.java:59)

at java.lang.J9VMInternals.initialize(J9VMInternals.java:120)

at WhichClassLoader1.main(WhichClassLoader1.java:17)

正 如所看到的,由于WhichClassLoader3 在应用程序类路径下,程序失败,收到一个NoClassDefFoundError 的异常,这看起来有些奇怪。问题在于:它现在在一个错误的类路径下面。当WhichClassLoader2被扩展类加载器加载的时候,发生了什么呢?实 际上,应用程序类加载器委托扩展类加载器加载WhichClassLoader2,扩展类加载器又委托引导类加载器。由于引导类加载器找不到这个类,类加 载的控制就会返回给扩展类加载器。扩展类加载器在自己的路径下找到了这个类将它加载。现在,当一个类已经被类加载器加载后,这个类需要的任何其他的新类都 必须用同一个类加载器加载他们(或者遵循父委托模式,由父类加载器加载)。所以当WhichClassLoader2 需要访问WhichClassLoader3 的时候,扩展类加载器就会获得这个请求去加载WhichClassLoader3,扩展类加载器先委托引导类加载器,但是引导类加载器找不到这个类,于是 扩展类加载器便试图装入自身但是也找不到这个类,原因是WhichClassLoader3不在扩展类路径而是在应用程序类路径。由于扩展类加载器无法委 托应用程序类加载器,所以就会出现NoClassDefFoundError 的异常。

?

?注意:开发者通常会使用如下语法通过类加载器机制加载属性文件:

Properties p = new Properties();

p.load(MyClass.class.getClassLoader().getResourceAsStream("myApp.properties"

));

这个意思是:如果MyClass 由扩展类加载器加载,而 myApp.properties 文件只能应用程序类加载器看到,则装入属性文件就会失败。

?

??

?

?


lihe2008125??
    访问:66281次积分:1984分排名:第3786名原创:114篇转载:79篇译文:11篇评论:23条文章搜索文章分类
      C(12)Eclipse(29)Java(93)Linux and Mac(48)Mozilla(4)Web 前端(8)Windows(1)数据库(30)测试(3)英语(1)RMI(0)面试(1)Web 2.0 服务端(1)Flex AS3(2)文章存档2013年04月(1)2013年03月(1)2013年01月(7)2012年11月(9)2012年09月(1)展开阅读排行
        MAC 系统的启动过程和系统启动时运行shell 脚本(5270)DOM4J中文问题 Invalid byte 1 of 1-byte UTF-8 sequence.(3928)Java类加载器介绍(3478)[Java] ConcurrentMap 分析和思考(1991)Eclipse任务视图的用法(Task View)(1955)Eclipse CNF 视图制作(1830)Ant 常用任务(1752)Mac 下制作 安装包(1688)Eclipse中的IFile与File和Eclipse中文件同步问题(1374)String与Integer 之间的转换(978)评论排行
          DOM4J中文问题 Invalid byte 1 of 1-byte UTF-8 sequence.(5)[Java] BlockingQueue 简介(4)Sping3.0.3 and JPA2.0(3)Eclipse CNF 视图制作(3)[Java 多线程] 变量可见性(2)Java类加载器介绍(2)Eclipse 启动分析(1)Eclipse3.5 RCP(1)Mac 下制作 安装包(1)shell 和 applescript 互相调用(1)推荐文章最新评论
            Java类加载器介绍

            Allen_Zhao_2012: 不错,明白了

            Mac 下制作 安装包

            寒山-居士: 学习中,希望对我有帮助

            [Java] BlockingQueue 简介

            love425429: ...

            [Java] BlockingQueue 简介

            wanghexin701: 写的言简意赅 不错 期待下文

            [Java] BlockingQueue 简介

            javaliuliu: 。。。

            [Java] BlockingQueue 简介

            cslr789:

            [Java 多线程] 变量可见性

            lihe2008125: confirm ithttp://www.danasoft.com/sig/alf2008125.j...

            [Java 多线程] 变量可见性

            lihe2008125: hehe

            Eclipse 启动分析

            juvencoco: good,最近正在看equinox代码

            Sping3.0.3 and JPA2.0

            lihe2008125: 回复 pandaxba:报什么错误啊?Spring 3.0.3 支持JPA2.0, 如果在不成功,我...

            大牛的Bolg
              梁斌的博客robbin 的博客一直都有新高度庄表伟刘刚[Eclipse&Android]Macming张洋好友的Bolg
                小乔的博客

                ?

热点排行