没有合适的资源?快使用搜索试试~ 我知道了~
每个java开发人员对java.lang.ClassNotFoundExcetpion这个异常肯定都不陌生,这背后就涉及到了java技术体系中的类加载。Java的类加载机制是java技术体系中比较核心的部分,虽然和大部分开发人员直接打交道不多,但是对其背后的机理有一定理解有助于排查程序中出现的类加载失败等技术问题,对理解java虚拟机的连接模型和java语言的动态性都有很大帮助。
资源推荐
资源详情
资源评论
Java 类加载原理解析
1 基本信息
摘要:
每个 java 开发人员对 java.lang.ClassNotFoundExcetpion 这个
异常肯定都不陌生,这背后就涉及到了 java 技术体系中的类加载。
Java
的类加载机制是 java 技术体系中比较核心的部分,虽然和大部分
开发人员直接打交道不多,但是对其背后的机理有一定理解有助于排查
程序中出现的类加载失败等技术问题,对理解 java 虚拟机的连接模型
和 java 语言的动态性都有很大帮助。
由于关于 java 类加载的内容较多,所以打算分三篇文章简述一下:
第一篇:java 类加载原理解析
第二篇:插件环境下类加载原理解析
第三篇:线程上下文类加载器
2 Java
虚拟机类加载器结构简述
2.1 JVM 三种预定义类型类加载器
我们首先看一下 JVM 预定义的三种类型类加载器,当一个 JVM 启
动的时候,Java 缺省开始使用如下三种类型类装入器:
启动(Bootstrap)类加载器:引导类装入器是用本地代码实现
的类装入器,它负责将 <Java_Runtime_Home>/lib 下面的类库加载
到内存中。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法
直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。
标准扩展(Extension)类加载器:扩展类加载器是由 Sun 的
ExtClassLoader(sun.misc.Launcher$ExtClassLoader) 实现的。它负
责将 < Java_Runtime_Home >/lib/ext 或者由系统变量 java.ext.dir 指
定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器。
系统(System)类加载器:系统类加载器是由 Sun 的
AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的。
它负责将系统类路径(CLASSPATH)中指定的类库加载到内存中。开
发者可以直接使用系统类加载器。
除了以上列举的三种类加载器,还有一种比较特殊的类型就是线程
上下文类加载器,这个将在后面单独介绍。
2.2 类加载双亲委派机制介绍和分析
****** 在这里,需要着重说明的是,JVM 在加载类时默认采用的是双亲
委派机制。通俗的讲,就是某个特定的类加载器在接到加载类的请求时,
首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完
成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,
才自己去加载。关于虚拟机默认的双亲委派机制,我们可以从系统类加
载器和标准扩展类加载器为例作简单分析。
****** 类加载器均是继承自 java.lang.ClassLoader 抽象类。我们下面
我们就看简要介绍一下 java.lang.ClassLoader 中几个最重要的方法:
//加载指定名称(包括包名)的二进制类型,供用户调用的接口
public Class<?> loadClass(String name) throws
ClassNotFoundException{//…}
//加载指定名称(包括包名)的二进制类型,同时指定是否解析(但是,
这里的 resolve 参数不一定真正能达到解析的效果~_~),供继承用
protectedsynchronized Class<?> loadClass(String name,
boolean resolve) throws ClassNotFoundException{//…}
//4ndClass 方法一般被 loadClass 方法调用去加载指定名称类,供继
承用
protected Class<?> ndClass(String name) throws
ClassNotFoundException {//…}
//定义类型,一般在 4ndClass 方法中读取到对应字节码后调用,可以
看出不可继承(说明:JVM 已经实现了对应的具体功能,解析对应的字
节码,产生对应的内部数据结构放置到方法区,所以无需覆写,直接调
用就可以了)
protected 4nal Class<?> deneClass(String name, byte[] b,
int o8, int len)
throws ClassFormatError{//…}
****** 通过进一步分析标准扩展类加载器
(sun.misc.Launcher$ExtClassLoader)和系统类加载器
(sun.misc.Launcher$AppClassLoader)的代码以及其公共父类
(java.net.URLClassLoader 和
java.security.SecureClassLoader)的代码可以看出,都没有覆写
java.lang.ClassLoader 中默认的加载委派规则---loadClass(…)方
法。既然这样,我们就可以通过分析 java.lang.ClassLoader 中的
loadClass(String name)方法的代码就可以分析出虚拟机默认采用
的双亲委派机制到底是什么模样:
public Class<?> loadClass(String name)throws ClassNotFoundException {
return loadClass(name, false);
}
protectedsynchronized 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 {
//如果不存在父类加载器,就检查是否是由启动类加载器加载的类,通过调用本地
方法 native Class findBootstrapClass(String name)
c = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
// 如果父类加载器和启动类加载器都不能完成加载任务,才调用自身的加载功能
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
通过上面的代码分析,我们可以对 JVM 采用的双亲委派类加载机制有了更
感性的认识,下面我们就接着分析一下启动类加载器、标准扩展类加载器和系
统类加载器三者之间的关系。可能大家已经从各种资料上面看到了如下类似的
一幅图片:
********************
*************************** *图三 类加载器默认委派关系图
上面图片给人的直观印象是系统类加载器的父类加载器是标准扩展类加载器,
标准扩展类加载器的父类加载器是启动类加载器,下面我们就用代码具体测试
一下
示例代码:
publicstaticvoid main(String[] args) {
try {
System.out.println(ClassLoader.getSystemClassLoader());
System.out.println(ClassLoader.getSystemClassLoader().getParent(
);
剩余17页未读,继续阅读
资源评论
hi2008111
- 粉丝: 2
- 资源: 2
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功