`

java与tomcat类加载机制

    博客分类:
  • java
阅读更多

前言:

类加载机制,听起来“高大上”的东西,其实不是很难。理解类加载机制,对我们日常的开发和对tomcat的理解会有一个提升。

一  java的类加载机制。

    1, java中类加载器的种类以及作用。

         (1)bootstrap            启动类加载器  JVM实现的一部分,在JVM运行的时候就加载 JAVA的核心API(java.lang.* or java.io.*)

         (2)ExtClassLoder     扩展类加载器  用来加载 java扩展的API 也就<JRE>/lib/ext 下面的类

         (3)AppClassLoder   系统类加载器  加载CLASSPATH下面的类,也就是用户自己写的类

 

    2, java类加载器的层次关系 和 调用顺序

          加载顺序 :按照从上到下的顺序 加载 类

          bootstrap 类加载器是由C++代码实现的 位于顶层

          ExtClassLoder 类加载器 位于中层

          AppClassLoder 类加载器 位于底层   

          注意:(ExtClassLoder 是 AppClassLoder 的父类 两者由java代码实现)

 

   3, java类加载器的双亲委托模型

       

 

        当一个类加载请求加载某个类的时候,首先检查是否已经加载过这个类,如果加载过直接返回。如果没有加载过,首先会委托父类加载器,父类加载器也会检查时候加载过这个类,如果还是没有则继续向上委托

        如果最后的父类加载器不能加载这个类。则调用 bootstrap 去加载这个类,如果还是找不到则会抛出ClassNotFoundException。

        这种模型的用途就是为了解决 类载入过程中的安全性问题。如果有恶意用户自定义了 一个类 如Object 类 去覆盖 java 关键类 则会有产生安全性问题。

    4,加载器的命名空间 

        每个加载器都有自己的命名空间,命名空间由该加载器以及父类所有的加载器所加载的类组成,当加载器加载一个雷的时候

首先会去自己的命名空间中查找 是否 加载过这个类。

        在同一命名空间不会出现出现类的完整名字完全相同的两个类,在不同的命名空间中有可能出现类的完整名字完全相同的两个类。

类加载器 命名空间
Loader1 Class1
Loader2 Class1Class2
Loader3 Class1Class2Class3
Loader4 Class1Class2Class3

 

5, 运行时包

      由同一类加载器加载属于相同包的类,组成了运行时包。

      决定两个类是否属于同一运行时包,不仅要看包名是否相同,还要看是否由,同一个ClassLoader加载。只有属于同一运行时包的类,才能互相访问包可见的类和成员。

      这样的限制避免了用户自己的代码冒充核心类库的类访问核心类库包可见成员的情况。假设用户自己定义了一个类 java.lang.xxx ,并用自定义的 ClassLoader 装载,由于 Java.lang.* 和 java.lang.xxx 是由不同的装载器装载,属于不同的运行时包,所以 java.lang.xxx 不能访问核心类库 java.lang 中类的包可见成员。

 

二  Tomcat 类加载机制。

先上一张tomcat 5的类 tomcat类加载器的结构图,虽然东西老,但是原理相同。

          Bootstrap
                  |
              System
                  |
            Common
          /                \
 Catalina          Shared
                      /  ... ...    \
            webapp1        webappN 

(1)Bootstrap:该加载器包含由JVM提供的基本的运行时类,加上放置在系统扩展目录(<JAVA_HOME/jre/lib/ext>)的JAR文件中的类。

注意——有些Java虚拟器(JVMs)也许把它作为不止一个类装载器用,或者作为一个类装载器用。

(2)System - 这个类装载器通常是以CLASSPATH环境变量的内容为基础来初始化的。在使用Tomcat作为Servlet/JSP容器的Web环境中,Tomcat在启动过程中清除了原有CLASSPATH的内容,并对其进行了重新定义。

  • $CATALINA_HOME/bin/bootstrap.jar - 包含用来初始化Tomcat 5服务器的main()方法,以及它所依赖的类装载器执行类。 

  • $JAVA_HOME/lib/tools.jar - 包含用来把JSP页面转换成servlet类的"javac"编译器。  

  • $CATALINA_HOME/bin/commons-logging-api.jar - Jakarta commons 记录应用程序界面。

  • $CATALINA_HOME/bin/commons-daemon.jar - Jakarta commons        daemon API.

  • jmx.jar - JMX 1.2 执行。

(3)Common:该类加载器包含一些对Tomcat内部类和web应用可见的额外类。其中包括1jasper-compiler.jar:JSP 2.0编译器(2)jsp-api.jar:JSP 2.0 API(3)servlet-api.jar:servlet 2.4 API等等。

(4)Catalina:该加载器初始化用来包含实现Tomcat 5本身所需要所有类和资源;

(5)Shared:在所有的web应用程序间共享的类和资源;

(6)WebappN:为每个部署在单个Tomcat 5实例上的Web应用创建的类加载器。加载/WEB-INF/classes和WEB-INF/lib下的类和资源

 

tomcat 的类加载机制与java的类加载委派模型不同之处就是,当WebappN被请求记载一个类的时候,并不一定完全会按照 java类加载器的委托模式,WebappN首先会在本地库中查找而不是直接委托。但是也有例外

作为 JRE 一些基本类的一部分类不能被覆盖

下面附上tomcat WebappClassLoader 的load方法

    public synchronized Class loadClass(String name, boolean resolve)  
            throws ClassNotFoundException {  
      
            Class clazz = null;  
      
            //首先检查已加载的类  
            // (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 = system.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;  
                        log.info(error, se);  
                        throw new ClassNotFoundException(error, se);  
                    }  
                }  
            }  
      
            boolean delegateLoad = delegate || filter(name);  
            //Tomcat允许按照配置来确定优先使用本Web应用的类加载器加载还是使用父类  
    //加载器来进行类加载,此处先使用父类加载器进行加载  
            // (1) Delegate to our parent if requested  
            if (delegateLoad) {  
                if (log.isDebugEnabled())  
                    log.debug("  Delegating to parent classloader1 " + 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) {  
                    ;  
                }  
            }  
            //使用本地的类加载器进行加载  
            // (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) {  
                ;  
            }  
            //如果没有特殊配置的话,使用父类加载器加载类  
            // (3) Delegate to parent unconditionally  
            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);  
      
        }  

 

 从一个网络程序的角度来看,类和资源的装载以这样的顺序在下列贮藏室进行查找:

  • 你的JVM的Bootstrap类
  • 系统类装载器类(描述如上)
  • 你的网络程序的/WEB-INF/classes
  • 你的网络程序的/WEB-INF/lib/*.jar
  • $CATALINA_HOME/common/classes
  • $CATALINA_HOME/common/endorsed/*.jar
  • $CATALINA_HOME/common/lib/*.jar
  • $CATALINA_BASE/shared/classes
  • $CATALINA_BASE/shared/lib/*.jar
  • 大小: 88.1 KB
分享到:
评论

相关推荐

    tomcat 类加载机制 —— ClassLoader

    在Java Web开发中,Tomcat作为最常用的Servlet容器,其类加载机制对于理解和优化应用性能至关重要。本文将深入探讨Tomcat的ClassLoader是如何工作的,以及它如何影响到我们的应用程序。 首先,理解类加载器...

    tomcat类加载器

    在Tomcat中,类加载机制的设计是为了支持多个Web应用程序的隔离运行。每个Web应用都有自己的类加载器,这样可以确保一个应用的类不会意外地与另一个应用的类混淆。默认的类加载器结构包括以下层次: 1. Bootstrap ...

    java类加载器-tomcat中的类加载器

    Tomcat,作为广泛使用的Java Servlet容器,它自定义了一套类加载机制,以满足Web应用程序的特殊需求。下面我们将深入探讨Java类加载器以及Tomcat中的类加载器。 在Java中,类加载器主要分为三个层次:Bootstrap ...

    Java 类在 Tomcat 中是如何加载的(过程分析)

    Tomcat有自己的类加载层次结构,这与JVM的加载机制略有不同: - **Bootstrap类加载器**:负责加载JVM运行所必需的基础类和标准扩展类。 - **System类加载器**:加载Tomcat启动所需的类,如bootstrap.jar。 - **...

    让tomcat自动加载修改过的类和servlet

    在IT领域,特别是Java Web开发中,Tomcat作为一款广泛使用的Servlet容器,其高效性和灵活性备受开发者青睐。然而,在开发过程中,频繁的代码修改与测试往往伴随着重启服务器的不便,这不仅消耗时间,还可能打断...

    译 Java类加载机制(二)

    Java类加载机制是Java平台设计的核心部分之一,它负责将.class文件从磁盘或网络中读取,并转换成运行时的Java对象。本篇将深入探讨这一机制的各个方面,包括类加载器、类加载过程以及双亲委派模型。 首先,我们要...

    Tomcat启动时类加载顺序

    #### 二、类加载机制概述 在Java中,类加载器(ClassLoader)负责将.class文件加载到JVM中。Tomcat通过自定义的类加载器实现了特定的类加载顺序,以确保能够正确处理不同来源的类文件,避免类的重复加载和类版本冲突...

    类加载器与Tomcat

    在Java的运行环境中,类加载器扮演着至关重要...在处理类冲突、版本控制和热部署等问题时,理解Tomcat的类加载机制至关重要。开发者在进行应用部署和配置时,必须考虑到类加载器的层次和行为,以避免潜在的问题和冲突。

    类加载器(java)

    类加载器的工作机制遵循“双亲委派模型”:当一个类加载器接收到加载类的请求时,它首先会委托父加载器去尝试加载,只有在父加载器无法加载的情况下,子加载器才会尝试自己去加载。这种设计可以防止类的重复加载,并...

    java和tomcat源码

    深入学习Java源码有助于理解其内部工作原理,包括类加载、内存管理、垃圾回收、多线程、异常处理等机制。你可以通过阅读和分析Java的OpenJDK源码来探索这些概念,OpenJDK是Java Development Kit(JDK)的一个开源...

    java利用ManagementFactory获取tomcat的一些信息例子

    在Java编程语言中,我们可以利用Java管理扩展(Java Management Extensions, JMX)和ManagementFactory类来获取应用程序,如Tomcat服务器的运行时信息。本文将深入探讨如何通过这些工具来监控Tomcat的一些关键信息。...

    JVM、Tomcat、OSGI等类加载器整理文档

    - Tomcat作为流行的Java Web服务器,有自己的类加载机制。它包括Web应用程序类加载器,用于加载特定Web应用的类,以及全局类加载器,用于共享所有应用的类。这种设计允许Web应用独立更新而不影响其他应用。 5. 类...

    myeclipse下tomcat动态加载

    在开发过程中,如果开启了自动发布,那么当保存修改后的Java类或JSP文件时,MyEclipse会自动将这些变化同步到Tomcat中,从而实现热更新。 4. **注意事项**:虽然动态加载和热更新提高了开发效率,但也有其局限性。...

    Tomcat加载顺序

    Apache Tomcat作为一款广泛使用的开源Servlet容器,其类加载机制是理解和维护基于Tomcat的应用程序的重要部分。Tomcat的类加载器遵循特定的加载顺序,确保了不同应用间的隔离性和资源的正确加载。下面将详细解析...

    java 反射运行时加载外部jar到Tomcat StandardClassLoader1

    总的来说,这段代码展示了如何利用 Java 反射机制在 Tomcat 中动态加载外部 JAR 文件,并执行其中的类和方法。需要注意的是,这种做法通常只适用于开发或测试环境,不推荐在生产环境中频繁使用,因为它可能会影响...

    Tomcat 类加载器的实现方法及实例代码

    Tomcat 类加载器的实现主要围绕着Java的类加载机制进行,旨在确保应用之间的类隔离,并提供灵活的资源访问策略。下面我们将深入探讨这些知识点。 首先,Java的类加载机制是基于“双亲委托模型”的。当一个类加载器...

    tomcat的工作原理

    Tomcat的工作原理涉及到多个组件,包括连接器(Connectors)、容器(Containers)、管道(Pipelines)与阀门(Valves),以及生命周期管理机制等。本文将详细探讨这些关键组成部分,揭示Tomcat如何高效地处理HTTP...

    开发Java的Tomcat6.0版本的服务器

    4. **部署**:在Tomcat中部署Java Web应用通常涉及创建一个WAR(Web ARchive)文件,这是包含所有Web应用资源(如HTML、CSS、JavaScript、Servlet类和JSP文件)的压缩文件。将WAR文件复制到Tomcat的`webapps`目录下...

    tomcat 源码分析系列文档

    5. "tomcat加载类的顺序.doc":详细说明了Tomcat加载类的具体步骤和顺序,这对于理解和调试类加载问题至关重要。 6. "Tomcat源码研究.pdf":提供了一个全面的源码分析概览,可能包括了Tomcat的主要组件、设计模式...

Global site tag (gtag.js) - Google Analytics