JAVA类加载机制以及如何自定义类加载器
来源:互联网 发布:linux 视频剪辑软件 编辑:程序博客网 时间:2024/06/05 19:50
原文链接:http://xtuhcy.iteye.com/blog/2305410
从双亲委派说起
- 启动(Bootstrap)类加载器:是用本地代码实现的类装入器,它负责将 <Java_Runtime_Home>/lib下面的类库加载到内存中(比如rt.jar)。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。
- 标准扩展(Extension)类加载器:是由 Sun 的 ExtClassLoader(sun.misc.Launcher$ExtClassLoader)实现的。它负责将< Java_Runtime_Home >/lib/ext或者由系统变量 java.ext.dir指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器。
- 系统(System)类加载器:是由 Sun 的 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的。它负责将系统类路径(CLASSPATH)中指定的类库加载到内存中。开发者可以直接使用系统类加载器。 除了以上列举的三种类加载器,还有一种比较特殊的类型 — 线程上下文类加载器。
双亲委派机制描述
- 某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。
Tomcat的类加载机制
本文主要以tomcat7为例说明类加载机制,大家也可以参考tomcat7的类加载机制的官方文档。Tomcat7总的ClassLoader结构如下图:
Bootstrap | System | Common / \ Webapp1 Webapp2 ...
各个类加载器加载类的范围:
- Bootstrap:包括java虚机机的基本类,以及$JAVA_HOME/jre/lib/ext下的类。
- System:包括CLASSPATH环境变量的类,主要是$CATALINA_HOME/bin/bootstrap.jar和$CATALINA_BASE/bin/tomcat-juli.jar两个jar包
- Common:包括tomcat的基本类,主要是$CATALINA_BASE/lib下的所有jar包
- WebappX:应用相关类,保证应用之间的类隔离。先加载/WEB-INF/classes,再加载/WEB-INF/lib/*.jar
加载顺序默认如下
- Bootstrap classes of your JVM
- /WEB-INF/classes of your web application
- /WEB-INF/lib/*.jar of your web application
- System class loader classes (described above)
- Common class loader classes (described above)
如果设置了<Loader delegate="true"/>,加载顺序如下:
- Bootstrap classes of your JVM
- System class loader classes (described above)
- Common class loader classes (described above)
- /WEB-INF/classes of your web application
- /WEB-INF/lib/*.jar of your web application
JavaEE的 委派模型
每个方块都是一个类加载器,JavaEE规范推荐每个模块的类加载器先加载本类加载的内容,如果加载不到才回到parent类加载器中尝试加载。
反转委派原则的原因是应用服务器中所携带的类库并不是应用所期待的,也许不适合应用开发者,一个常见的例子就是log4j的依赖在容器和不同的应用中都存在,但是它们的版本大都不同。
Tomcat的 类加载顺序
在Tomcat中,默认的行为是先尝试在Bootstrap和Extension中进行类型加载,如果加载不到则在WebappClassLoader中进行加载,如果还是找不到则在Common中进行查找。
setContextClassLoader的理解
JDK的解释是这样的:
Sets the context ClassLoader for this Thread. The context ClassLoader can be set when a thread is created, and allows the creator of the thread to provide the appropriate class loader, through , to code running in the thread when loading classes and resources.
并不是给线程设置了ContextClassLoader,这个线程下加载的类就都使用该ContextClassLoader。ContextClassLoader的用途是提供一个途径,使得线程运行时可以随时获得指定的ContextClassLoader进行类的加载,通过这个这种方式可以避开双亲委派模型,最典型的应用是JDBC、JNDI。
自定义的ClassLoader
自定义的ClassLoader通过继承ClassLoader来实现,也可以使用URLClassLoader更简单。如果需要改写类的加载过程最好覆盖findClass()而不是loadClass(),loadClass()是为了保持jdk1.2之前的兼容。使用findClass()能保证不会违背双亲委派模式。
如何使用自定义的ClassLoader new出对象呢?前面说过的setContextClassLoader是不对的,必须用自定义的ClassLoader,通过反射实例化一个初始类,由该初始类加载的其他类就都会使用自定义的ClassLoader了。可以分析一下tomcat的代码:
Class<?> startupClass = catalinaLoader.loadClass ("org.apache.catalina.startup.Catalina"); Object startupInstance = startupClass.newInstance();
通过反射机制调用startupInstance的方法,之后的类就会都有自定义的ClassLoader加载,当然有个前提就是不能违背双亲委派模型——自定义的ClassLoader加载的类在父ClassLoader加载的类中不存在。为什么要这么做?类加载的时候有一个规律,被加载类使用调用者所用的ClassLoader进行类的加载。可以通过Class.forName()的代码得到这个结论:
public static Class<?> forName(String className) throws ClassNotFoundException { Class<?> caller = Reflection.getCallerClass(); return forName0(className, true, ClassLoader.getClassLoader(caller), caller);}
- JAVA类加载机制以及如何自定义类加载器
- JAVA类加载机制以及如何自定义类加载器
- Java 类加载器以及加载机制
- 类加载机制实现原理以及自定义类加载器
- Java JVM:编译加载机制与自定义类加载器
- java的类加载机制以及加载模型
- java类加载器加载机制解析
- 浅谈Java 类加载器以及双亲委托机制
- java类加载器以及双亲委派机制
- Java中自定义类加载器(双亲委派机制)
- 类加载器的委托机制、自定义类加载器
- android中的类加载器,以及加载机制
- JVM:编译加载机制与自定义类加载器
- 关于JAVA的内省JavaBean、类加载器、类加载器的委托机制以及代理
- Java JVM 9:编译加载机制与自定义类加载器
- Java类加载机制
- java 类加载机制
- Java类加载机制
- 程序猿必备基础知识
- django+nginx 搭建
- 应用程序无法正常启动(0x0150002)
- java 类比较大小(实现Comparable接口)
- Android富文本编辑器总结(四)
- JAVA类加载机制以及如何自定义类加载器
- “我的未来网”不得不公开的商业秘密
- Nginx日志分割
- 模态对话框(window.showModalDialog),表单内容的提交、刷新父窗口的问题
- RPC和MQ对比及其适用/不适用场合
- DHTML技术演示---注册表单的验证且控制提交--前端校验(模拟网上账号注册)
- 高并发Java五 JDK并发包1
- 第十二周项目四String类的构造
- java连接sqlserver出现makeFromDatabaseError的问题