`

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);
    
                                   }
....

    }

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics