tomcat类加载器-with源码
来源:互联网 发布:显示数据库字符集 编辑:程序博客网 时间:2024/09/21 06:35
tomcat类加载器-with源码
基于Tomcat7
Bootstrap类public void init() throws Exception { // Set Catalina path setCatalinaHome(); setCatalinaBase(); initClassLoaders(); Thread.currentThread().setContextClassLoader(catalinaLoader); SecurityClassLoad.securityClassLoad(catalinaLoader); // Load our startup class and call its process() method if (log.isDebugEnabled()) log.debug("Loading startup class"); Class<?> startupClass = catalinaLoader.loadClass ("org.apache.catalina.startup.Catalina"); Object startupInstance = startupClass.newInstance(); // Set the shared extensions class loader if (log.isDebugEnabled()) log.debug("Setting startup class properties"); String methodName = "setParentClassLoader"; Class<?> paramTypes[] = new Class[1]; paramTypes[0] = Class.forName("java.lang.ClassLoader"); Object paramValues[] = new Object[1]; paramValues[0] = sharedLoader; Method method = startupInstance.getClass().getMethod(methodName, paramTypes); method.invoke(startupInstance, paramValues); catalinaDaemon = startupInstance; }
第三句:initClassLoaders(); //初始化各个类加载器对象
private void initClassLoaders() { try { commonLoader = createClassLoader("common", null); if( commonLoader == null ) { // no config file, default to this loader - we might be in a 'single' env. commonLoader=this.getClass().getClassLoader(); } catalinaLoader = createClassLoader("server", commonLoader); sharedLoader = createClassLoader("shared", commonLoader); } catch (Throwable t) { handleThrowable(t); log.error("Class loader creation threw exception", t); System.exit(1); }}
包括commonLoader、sharedLoader、catalinaLoader
使用前面已经构件好的catalinaLoader加载tomcat最核心的对象,那就是org.apache.catalina.startup.Catalina类的对象catalinaDaemon,并以反射的方式调用其setParentClassLoader方法,把sharedLoader作为参数传入
init()过程中:
Bootstrap类持有的几个对象(catalinaDaemon、commonLoader、sharedLoader、catalinaLoader)都得到了创建和必要的初始化,并且在main()
方法中知道init()方法完成才set daemon
Tomcat类加载器
为了支持和分隔多个web app,使用了WebappClassLoader,在实现上,它打破了系统默认规则,或者说是打破了java.lang.ClassLoader逻辑中的“双亲委派”模式,提供了一套自定义的类加载流程。
public class WebappClassLoader extends WebappClassLoaderBase public abstract class WebappClassLoaderBase extends URLClassLoader
WebappClassLoaderBase它覆盖了父类URLClassLoader中的loadClass方法,改变了默认的类加载顺序。
public Class loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLockInternal(name)) { if (log.isDebugEnabled()) log.debug("loadClass(" + name + ", " + resolve + ")"); Class<?> clazz = null; // Log access to stopped classloader if (!started) { try { throw new IllegalStateException(); } catch (IllegalStateException e) { log.info(sm.getString("webappClassLoader.stopped", name), e); } } // (0) Check our previously loaded local class cache //当前类加载器的缓存 clazz = findLoadedClass0(name); if (clazz != null) { if (log.isDebugEnabled()) log.debug(" Returning class from cache"); if (resolve) resolveClass(clazz); return (clazz); } // (0.1) Check our previously loaded class cache //父类加载器的缓存 clazz = findLoadedClass(name); if (clazz != null) { if (log.isDebugEnabled()) log.debug(" Returning class from cache"); if (resolve) resolveClass(clazz); return (clazz); } // (0.2) Try loading the class with the system class loader, to prevent // the webapp from overriding J2SE classes //系统类加载器 try { clazz = j2seClassLoader.loadClass(name); if (clazz != null) { if (resolve) resolveClass(clazz); return (clazz); } } catch (ClassNotFoundException e) { // Ignore } // (0.5) Permission to access this class when using a SecurityManager if (securityManager != null) { int i = name.lastIndexOf('.'); if (i >= 0) { try { securityManager.checkPackageAccess(name.substring(0,i)); } catch (SecurityException se) { String error = "Security Violation, attempt to use " + "Restricted Class: " + name; if (name.endsWith("BeanInfo")) { // BZ 57906: suppress logging for calls from // java.beans.Introspector.findExplicitBeanInfo() log.debug(error, se); } else { log.info(error, se); } throw new ClassNotFoundException(error, se); } } } boolean delegateLoad = delegate || filter(name); // (1) Delegate to our parent if requested //如果设置delegate,先由父类加载器加载,默认false if (delegateLoad) { if (log.isDebugEnabled()) log.debug(" Delegating to parent classloader1 " + parent); try { clazz = Class.forName(name, false, parent); if (clazz != null) { if (log.isDebugEnabled()) log.debug(" Loading class from parent"); if (resolve) resolveClass(clazz); return (clazz); } } catch (ClassNotFoundException e) { // Ignore } } // (2) Search local repositories if (log.isDebugEnabled()) log.debug(" Searching local repositories"); try { clazz = findClass(name); if (clazz != null) { if (log.isDebugEnabled()) log.debug(" Loading class from local repository"); if (resolve) resolveClass(clazz); return (clazz); } } catch (ClassNotFoundException e) { // Ignore } // (3) Delegate to parent unconditionally if (!delegateLoad) { if (log.isDebugEnabled()) log.debug(" Delegating to parent classloader at end: " + parent); try { clazz = Class.forName(name, false, parent); if (clazz != null) { if (log.isDebugEnabled()) log.debug(" Loading class from parent"); if (resolve) resolveClass(clazz); return (clazz); } } catch (ClassNotFoundException e) { // Ignore } } } throw new ClassNotFoundException(name);}
首先findLoadedClass0()和findLoadedClass()分别从本地和父类加载器的缓存中查找当前要加载的类是否已经加载过了。之后Tomcat类加载器会将加载请求委派给系统类加载器。接下来根据delegate变量的设置,决定是先由自己加载,
还是先由父类加载器去加载。
其中:WebappClassLoader是对应一个Web应用的类加载器,其父亲是Tomcat的lib的加载器,即Common 通用类加载。如果配置 ,那么加载顺序将改变:
- JVM 的 Bootstrap 类
- System 类加载器的类(如上所述)
- Common 类加载器的类(如上所述)
- Web 应用的 /WEB-INF/classes 类
- Web 应用的 /WEB-INF/lib/*.jar 类
本来的类加载顺序参考上篇文章:
http://blog.csdn.net/cx520forever/article/details/50780461
如果想要在Web应用间共享一些Jar包,则不仅需要将公共包放在Tomcat的lib下,还要删掉Web应用lib中的包,否则Tomcat启动时还是会优先加载Web应用lib下的包的。
- tomcat类加载器-with源码
- Tomcat源码分析-类加载器
- [Tomcat源码系列] Tomcat 类加载器结构
- (八)Tomcat源码解析 - Tomcat类加载器原理
- Tomcat类加载器机制(Tomcat源码解析六)
- Tomcat类加载器机制(Tomcat源码解析六)
- [Tomcat源码系列] Tomcat 类加载器结构
- Tomcat源码阅读系列(六)类加载器
- Tomcat源码解析(六):类加载器
- tomcat6源码研究:tomcat类加载机制
- Tomcat WebappClassLoader 类加载机制源码分析
- Tomcat源码学习--WebAppClassLoader类加载机制
- Tomcat的类加载体系及Tomcat源码
- Tomcat类加载器
- tomcat类加载器
- tomcat类加载器
- 从Tomcat源码看其类加载实现
- 【Web容器】Tomcat源码分析(1)-类加载体系
- iOS 关键帧动画 详解
- linux-qt-qmake
- 导入外部css文件时link和@import的区别
- [Android]如何让ListView显示不同布局的解决方式和案例
- JSP 中文问题完全解决方案
- tomcat类加载器-with源码
- wmap安装过程的问题解决
- ViewPager+LinearLayout实现带索引的图片滑动
- HDU2504又见GCD
- 数据结构(5)线性表之链表C++实现带头结点的单链表合并
- Hadoop FS Shell命令大全
- 数组面试题
- MATLAB下载及安装
- ZBrush中的Alt和Shift键该如何进行运用