与
C
或
C++
编写的程序不同,
Java
程序并不是一个可执行文件,而是由许多独立的类文件组成,每一个文件对应于一个
Java
类。此外,这些类文件并非立即全部都装入内存,而是根据程序需要装入内存。
ClassLoader
是
JVM
中将类装入内存的那部分。而且,
Java ClassLoader
就是用
Java
语言编写的。这意味着创建您自己的
ClassLoader
非常容易,不必了解
JVM
的微小细节。
Java
的
classloader
不但可以使你运行本地得
class
类
,
你也可以定制
classloader
运行来自远程的字节代码
.
ClassLoader
的基本目标是对类的请求提供服务。当
JVM
需要使用类时,它根据名称向
ClassLoader
请求这个类,然后
ClassLoader
试图返回一个表示这个类的
Class
对象。
通过覆盖对应于这个过程不同阶段的方法,可以创建定制的
ClassLoader
。通常当你需要动态加载资源的时候
,
你至少有三个
ClassLoader
可以选择
:
1.
系统类加载器(应用类加载器)
(system classloader or application classloader)
2.
当前类加载器
3.
当前线程类加载器
第一种
:
系统类加载器
系统类加载器
(system classloader).
这个类加载器处理
-classpath
下的类加载工作
,
可以通过
ClassLoader.getSystemClassLoader()
方法调用
.
ClassLoader
下所有的
getSystemXXX()
的静态方法都是通过这个方法定义的
.
在你的代码中
,
你应该尽量少地调用这个方法
,
以其它的类加载器作为代理
.
否则你的代码将只能工作在简单的命令行应用中
,
这个时候系统类加载器
(system classloader)
是
JVM
最后创建的类加载器
.
一旦你把代码移到
EJB, Web
应用或
Java Web Start
应用中
,
一定会出问题
.
Class.loadClass( String name, boolean resolve );
name
参数指定了
JVM
需要的类的名称,该名称以包表示法表示,如
Foo
或
java.lang.Object
。
resolve
参数告诉方法是否需要解析类。在准备执行类之前,应考虑类解析。并不总是需要解析。如果
JVM
只需要知道该类是否存在或找出该类的超类,那么就不需要解析。
方法
defineClass
是
ClassLoader
的主要诀窍。
该方法接受由原始字节组成的数组并把它转换成
Class
对象。原始数组包含如从文件系统或网络装入的数据。
defineClass
管理
JVM
的许多复杂、神秘和倚赖于实现的方面
--
它把字节码分析成运行时数据结构、校验有效性等等。不必担心,您无需亲自编写它。事实上,即使您想要这么做也不能覆盖它,因为它已被标记成最终的。
方法
findSystemClass
findSystemClass
方法从本地文件系统装入文件。它在本地文件系统中寻找类文件,如果存在,就使用
defineClass
将原始字节转换成
Class
对象,以将该文件转换成类。当运行
Java
应用程序时,这是
JVM
正常装入类的缺省机制
.
如果
ClassLoader
不能找到类,它会请求父代
ClassLoader
来执行此项任务。所有
ClassLoaders
的根是系统
ClassLoader
,它会以缺省方式装入类
--
即,从本地文件系统。
方法
findLoadedClass
充当一个缓存
当请求
loadClass
装入类时,它调用该方法来查看
ClassLoader
是否已装入这个类,这样可以避免重新装入已存在类所造成的麻烦。应首先调用该方法。
让我们看一下如何组装所有方法。
loadClass
实现示例执行以下步骤:
(这里,我们没有指定生成类文件是采用了哪种技术,它可以是从
Net
上装入、或者从归档文件中提取、或者实时编译。无论是哪一种,那是种特殊的神奇方式,使我们获得了原始类文件字节。)
1.
调用
findLoadedClass
来查看是否存在已装入的类。
2.
如果没有,那么采用那种特殊的神奇方式来获取原始字节。
3.
如果已有原始字节,调用
defineClass
将它们转换成
Class
对象。
4.
如果没有原始字节,然后调用
findSystemClass
查看是否从本地文件系统获取类。
5.
如果
resolve
参数是
true
,那么调用
resolveClass
解析
Class
对象。
6.
如果还没有类,返回
ClassNotFoundException
。
7.
否则,将类返回给调用程序。
第二种选择
:
当前上下文环境下的类加载器
.
根据定义,当前类加载器就是你当前方法所属的类的加载器。在运行时类之间动态联编,即调用
Class.forName()
,
Class.getResource()
等类似方法时,这个类加载器会被隐含地使用。
posted on 2006-08-20 20:59
Lizzie 阅读(255)
评论(0) 编辑 收藏 所属分类:
专业积木