读书人

TOMCAT-类加载器

发布时间: 2012-10-09 10:21:45 作者: rapoo

TOMCAT---类加载器

一、WebappClassLoader覆盖了classloader的loadclass方法

public synchronized Class loadClass(String name, boolean resolve)           throws ClassNotFoundException {             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) 检查自身缓存:WebappClassLoader之前是否已经load过这个资源   clazz = findLoadedClass0(name);           if (clazz != null) {               if (log.isDebugEnabled())                   log.debug("  Returning class from cache");               if (resolve)                   resolveClass(clazz);               return (clazz);           }             // (1) 检查上一级缓存:ClassLoader之前是否已经load过           clazz = findLoadedClass(name);           if (clazz != null) {               if (log.isDebugEnabled())                   log.debug("  Returning class from cache");               if (resolve)                   resolveClass(clazz);               return (clazz);           }             // (2) 先交由系统ClassLoader,因此WEB-INF/lib和WEB-INF/classes或{tomcat}/libs下的类定义不能覆盖JVM 底层能够查找到的定义(譬如不能通过定义java.lang.Integer替代底层的实现           try {               clazz = system.loadClass(name);               if (clazz != null) {                   if (resolve)                       resolveClass(clazz);                   return (clazz);               }           } catch (ClassNotFoundException e) {               // Ignore           }             // (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;                       log.info(error, se);                       throw new ClassNotFoundException(error, se);                   }               }           }             //这是一个很奇怪的定义,JVM的ClassLoader建议先由parent去load,load不到自己再去load(见如上 ClassLoader部分),而Servelet规范的建议则恰好相反,Tomcat的实现则做个折中,由用户去决定(context的 delegate定义),默认使用Servlet规范的建议,即delegate=false           boolean delegateLoad = delegate || filter(name);             // (1) 先由parent去尝试加载,此处的parent是SharedClassLoader,见如上说明,如上说明,除非设置了delegate,否则这里不执行           if (delegateLoad) {               if (log.isDebugEnabled())                   log.debug("  Delegating to parent classloader1 " + parent);               ClassLoader loader = parent;                //此处parent是否为空取决于context 的privileged属性配置,默认privileged=true,即parent为SharedClassLoader               if (loader == null)                   loader = system;               try {                   clazz = loader.loadClass(name);                   if (clazz != null) {                       if (log.isDebugEnabled())                           log.debug("  Loading class from parent");                       if (resolve)                           resolveClass(clazz);                       return (clazz);                   }               } catch (ClassNotFoundException e) {                   ;               }           }             // (2) 到WEB-INF/lib和WEB-INF/classes目录去搜索,细节部分可以再看一下findClass,会发现默认是先搜索WEB-INF/classes后搜索WEB-INF/lib           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) {               ;           }             // (3) 由parent再去尝试加载一下           if (!delegateLoad) {               if (log.isDebugEnabled())                   log.debug("  Delegating to parent classloader at end: " + parent);               ClassLoader loader = parent;               if (loader == null)                   loader = system;               try {                   clazz = loader.loadClass(name);                   if (clazz != null) {                       if (log.isDebugEnabled())                           log.debug("  Loading class from parent");                       if (resolve)                           resolveClass(clazz);                       return (clazz);                   }               } catch (ClassNotFoundException e) {                   ;               }           }             throw new ClassNotFoundException(name);       }  

?

二、WebappClassLoader定义了自己的findclass方法

    public Class findClass(String name) //调用    protected Class findClassInternal(String name)//调用    protected ResourceEntry findResourceInternal(String name, String path) {....        for (i = 0; (entry == null) && (i < repositoriesLength); i++) {            try {                String fullPath = repositories[i] + path;//repositories里面只有一个值,即:WEB-INF/classes                Object lookupResult = resources.lookup(fullPath);                if (lookupResult instanceof Resource) {                    resource = (Resource) lookupResult;                }                // Note : Not getting an exception here means the resource was                // found                entry = findResourceInternal(files[i], path);                ResourceAttributes attributes =                    (ResourceAttributes) resources.getAttributes(fullPath);                contentLength = (int) attributes.getContentLength();                entry.lastModified = attributes.getLastModified();                if (resource != null) {                    try {                        binaryStream = resource.streamContent();                    } catch (IOException e) {                        return null;                    }                    if (needConvert) {                        if (path.endsWith(".properties")) {                            fileNeedConvert = true;                        }                    }....                }            } catch (NamingException e) {            }        }        if ((entry == null) && (notFoundResources.containsKey(name)))//这里已经缓存了加载失败的类名字以提高性能。            return null;        JarEntry jarEntry = null;        synchronized (jarFiles) {//如果在WEB-INF/classes中没找到则在CLASSPATH中JAR里找            try {                if (!openJARs()) {                    return null;                }                for (i = 0; (entry == null) && (i < jarFilesLength); i++) {                        jarEntry = jarFiles[i].getJarEntry(path);                                       }....    }

?

读书人网 >编程

热点推荐