java类加载就是把二进制class文件加载到内存然后验证、解析、初始化的过程。执行这些内容的就是有我们熟知的类加载器来实现的。
类加载器
每一个类加载器都有一个独立的类名称空间。比较两个类是否相等的前提是同一类加载器加载。
从开发人员角度来看,类加载器可以分为下面三种类型
启动类加载器 Bootstrap ClassLoader
负责加载存放在 <JAVA_HOME>\lib目录或者 -Xbootclasspath指定目录下的符合名字要求的类库(如 rt.jar)加载到虚拟机内存中。名字不符合的类库即使放到该目录下也不会被加载。
扩展类加载器 Extension ClassLoader
负责加载存放在 <JAVA_HOME>\lib\ext目录的或者 java.ext.dirs系统变量指定的目录。开发者可以直接使用。
应用程序类加载器 Application ClassLoader
负责加载用户类路径(classpath)上所指定的类库,开发者可以直接使用,一般也是程序中默认的类加载器。
双亲委派
是Java设计者推荐给开发者的一种类加载器实现方式。
大概的工作流程:如果一个类加载器收到加载请求,它先询问自己的父级加载器是否能够加载,然后依次类推,直到传到顶层的启动类加载器。当父类加载器反馈无法加载时,子加载器才会尝试自己加载。
打破双亲委派
双亲委派只是一种建议的模型,在实际运用中有很多部分不遵守该模型的例子。
- 用户重写loadClass()方法实现自定义加载逻辑
- JAVA SPI
- 热部署,热加载等技术
- OSGi(Open Service Gateway Initiative)技术是Java动态化模块化系统的一系列规范。它实现模块化热部署的关键是它自定义的类加载机制的实现。每一个程序模块都有一个自己的类加载器。
规则如下(摘自《深入累计Java虚拟机》)
- 以 java.* 开头的类委派给父类加载器加载。(遵守双亲委派)
- 否则,将委派列表名单内的类委派给父类加载器加载。(遵守双亲委派)
- 否则,将Import列表中的类委派给Export这个类的Bundle的类加载器加载。
- 否则, 查找当前Bundle的classpath,使用自己的类加载器加载。
- 否则,查找类是否在自己的Fragment Bundle中,在的话则委派给Fragment Bundle的类加载器加载。
- 否则,查找Dynamic Import 列表的Bundle, 委派给对应的Bundle的类加载器加载。
- 否则, 类加载失败
有赞Aladdin的加载实践
为什么要搞一个Aladdin系统,在一个大集群分布式环境下,应用非常的多,所以急需要一个能够统一管理的平台,它的能力有下面几个
1.解决jar包版本冲突问题
2.统一管理jar包安全性、可靠性
3.统一管理jar包的升级
Aladdin的类加载大部分是通过http或者url的方式进行,所以直接继承了UrlClassLoader。而UrlClassLoader是 ExtClassLoader的父类,所以这里已经丝毫没有双亲委派的影子了。
UrlClassLoader的功能
1.可以从文件系统加载
2.可以从jar包进行加载
3.从远程Http服务进行加载
网友评论