没有合适的资源?快使用搜索试试~ 我知道了~
java ClassLoader机制及其在OSGi中的应用
5星 · 超过95%的资源 需积分: 35 26 下载量 81 浏览量
2011-05-19
23:35:12
上传
评论
收藏 751KB DOC 举报
温馨提示
试读
17页
内容简介: ClassLoader体系结构 类装载器在JVM中并不是唯一的,JVM自带了三个装载器,用户也可以根据自己的需求自定义新的装载器,这些装载器的体系结构可以看作是树状结构,如图1所示:
资源推荐
资源详情
资源评论
Java ClassLoader
一 基本概念
Java 中引入了虚拟机的概念,即在机器和编译程序之间加入了一层抽象虚拟的机器
(JVM)。 JVM 屏蔽了各平台之间的差异,从而使 Java 具有了跨平台的特点。
Java 程序并不是一个原生的可执行文件,而是由许多独立的.java 文件组成。每一个文件
对应一个 Java 类,编译之后会生成可以通过 JVM 执行的.class 文件。类装载器(ClassLoader)
的主要功能是将这些.class 文件根据程序需要动态的加载到 JVM 中。
二 ClassLoader 体系结构
类装载器在 JVM 中并不是唯一的,JVM 自带了三个装载器,用户也可以根据自己的需求
自定义新的装载器,这些装载器的体系结构可以看作是树状结构,如图 1 所示:
图 1 类加载器树状组织结构示意图
JVM 自带的三个类装载器分别是:
1. BootstrapClassLoader(启动类加载器)
用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader。
主要负责 jdk_home/lib 目录下的核心 api 或 -Xbootclasspath 选项指定的 jar 包。
2. ExtensionClassLoader(扩展类加载器)
用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此
目录里面查找并加载 Java 类。主要负责 jdk_home/lib/ext 目录下的 jar 包或 -Djava.ext.dirs 指
定目录下的 jar 包装入工作。
3. SystemClassLoader(系统类加载器)
功能描述:通常由 AppClassLoader 充当,它根据 Java 应用的类路径(CLASSPATH)
来 加 载 Java 类 。 一 般 来 说 , Java 应 用 的 类 都 是 由 它 来 完 成 加 载 的 。 可 以 通 过
ClassLoader.getSystemClassLoader() 来获取它。主要负责 java –classpath/-Djava.class.path 所
指的目录下的类与 jar 包装入工作。
在这些类装载器中,BootstrapClassLoader 是比较特殊的一个。BootstrapClassLoader 是
JVM 自带的类装载器,由 C++编写,在 JVM 运行的时候就已经存在了。java 的运行环境所需
要 的 所 有 类 库 都 由 它 来 装 载 。 ExtClassLoader 和 AppClassLoader 本 身 也 是 java 类 , 由
BootstrapClassLoader 装载到 JVM 之中。
下面用一个小例子测试三个 JVM 自带 ClassLoader 之间的关系:
例 1 JVM 自带 ClassLoader 关系的测试 (example 1)
public class ClassLoaderTest1 {
public static void main(String[] args) {
ClassLoader loader = ClassLoaderTest1.class.getClassLoader();
System.out.println("This Class is loaded by :" + loader);
System.out.println("AppClassLoader's father classLoader is :" +
loader.getParent());
System.out.println("ExtClassLoader's father classLoader is:" +
loader.getParent().getParent());
}
}
运行结果
This Class is loaded by :sun.misc.Launcher$AppClassLoader@19821f
AppClassLoader's father classLoader
is :sun.misc.Launcher$ExtClassLoader@addbf1
ExtClassLoader's father classLoader is:null
第一行表示,当前用户自定义的类由系统类装载器 AppClassLoader 进行装载。
第二行表示,系统类装载器的父加载器是扩展装载器 ExtClassLoader。
第三行表示,扩展装载器的父加载器载器为 启动类加载 bootClassLoader(由 bootStrap
classloader 不是标准的 java 类,所以在这里我们只能看到 null)。
三 ClassLoader 装载策略
从 1.2 版本开始,Java 引入了双亲委托模型,从而更好的保证了 Java 平台的安全。在此模
型下,当一个装载器被请求装载某个类时,它首先委托自己的 parent 去装载,若 parent 能装载,
则返回这个类所对应的 Class 对象,若 parent 不能装载,则由 parent 的请求者去装载。
具体顺序如图 2 所示:当 Java 中出现新的类,AppClassLoader 首先将类传递给它的父类类
装载器,也就是 ExtClassLoader,询问它是否能够装载该类。如果能,那 AppClassLoader 就不
再加载,同样 ExtClassLoader 在装载时,也会先问问它的父类装载器 BootClassloader 是否能加
载 , 如 果 能 则 由 BootClassLoader 加 载 。 当 BootClassLoader 无 法 加 载 的 时 候 , 则 返 回
ExtClassloader 一级,如果依然不能加载则再返回下面一级(AppClassLoader)。在基于类装载
器的树状的结构图中,每个类装载器有自己的父亲,类装载器在装载类时,总是先让自己的父
类装载器装载,如果父类装载器无法装载该类时,自己就会动手装载。如果自己也装载不了,
则报 Exception,class not found 的错误。
图 2 JVM ClassLoader 加载策略
这种加载策略形成了以下 java class 加载的顺序:
1. 首先加载核心 API,让系统最基本的运行起来
2. 加载扩展类
3. 加载用户自定义的类
在此模型下,系统会在用户自定义类加载之前,完成核心类的加载。也就是说,即使用户
定义了一个与系统核心类一模一样的类,也无法覆盖父加载器已经加载的核心类,从而防止了
由于用户重写系统类而带来的安全隐患。实际上,自定义类装载器的编写者可以自由定义装载
规则,不把装载权交给父装载类,但是可能带来不安全的问题。
四 自定义 ClassLoader 及使用方法
有时候,用户需要根据自己的需要定制自己的 ClassLoader。Java 规范规定,所有的用户
自定义 ClassLoader 都必须从抽象类“java.lang.ClassLoader”类继承而来。JVM 在加载类的时候,
是通过 ClassLoader 的 loadClass 方法来加载 class 的,在定制自己的 ClassLoader 之前,先看一
下这个函数的内部实现。
protected synchronized Class loadClass(String name, boolean resolve)
throws ClassNotFoundException {
// 首先, 检查这个类是否已经加载。
Class c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
// 如果仍然没有找到,那么就调用findclass查找这个类.
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
通常我们使用 ClassLoader.loadClass(String name)根据指定的类名得到一个相应的 Class 实
例。从 Java 源代码中我们可以看到,缺省的 ClassLoader 做了如下的工作:
1. 调用 FindLoadedClass(String):Class 检查一下这个 Class 是否已经被加载过了。由于
JVM 规范规定 ClassLoader 可以在缓存保留它所加载的 Class,因此如果一个 Class
已经被加载过,直接从缓存中获取即可。
2. 调用它的父类的 LoadClass()方法,如果它的父类不为空,让它的父类加载器加载。
3. 如 果 它 的 父 类 加 载 器 叠 代 后 也 无 法 加 载 这 个 Class , 则 使 用 JVM 内 部 的
ClassLoader(即著名的 BootstrapClassloader)来加载这个 Class。
如果上面三步都没有找到,就调用 findClass 方法从自己的加载空间查找加载这个 Class。
因此,如果我们希望自定义的 ClassLoader 能够保持系统类装器的装载策略,并不需要重
写 loadClass 方法,只要覆盖 FindClass 方法即可。
现在我们做一个最简单的自定义 ClassLoader,这个 ClassLoader 继承了系统类装载器的装
载策略,只是加载的路径不同。
例 2 自定义 ClassLoader 使用测试(example 2)
/** */
/**
* 自定义类加载器
*/
public class MyClassLoader extends ClassLoader {
private static String MyClasspath = new String("");
private static Hashtable loadClassHashTable = new Hashtable();
public MyClassLoader() {
}
剩余16页未读,继续阅读
资源评论
- spanel2013-03-15恩,这篇教程不错,初步了解了osgi机制
- kingkewow2012-09-24要了解OSGi,CLASSLOAD的知识是必须的,多谢分享
- hwhoho20102013-01-22一直 很迷糊 多谢
- hulibabaii2014-05-30相当于一个入门,这个入门写得深浅得当。
- fuqiang77312012-06-26之前遇到一个问题一直解决了,看完这个才知道原因是什么?
freezhenliu
- 粉丝: 12
- 资源: 21
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功