资讯专栏INFORMATION COLUMN

Tomcat 7 类加载器是如何实现的

trigkit4 / 704人阅读

摘要:请注意,应用程序类加载器的模型与此略有不同,如下所述,但主要原则是相同的。此类由加载器搜索的位置中的属性定义。该服务器类加载器是唯一到内部可见,并且是应用程序完全不可见。

Tomcat 7 类加载器是如何实现的 概述

与许多服务器应用程序一样,Tomcat安装了各种类加载器(即实现的类java.lang.ClassLoader),以允许容器的不同部分和容器上运行的Web应用程序访问可用类和资源的不同存储库。此机制用于提供Servlet规范2.4版中定义的功能 - 特别是9.4和9.6节。

在Java环境中,类加载器排列在父子树中。通常,当要求类加载器加载特定的类或资源时,它首先将请求委托给父类加载器,然后仅在父类加载器找不到所请求的类或资源时查找它自己的存储库。 。请注意,Web应用程序类加载器的模型与此略有不同,如下所述,但主要原则是相同的。

当Tomcat启动时,它会创建一组类加载器,这些加载器被组织成以下父子关系,其中父类加载器位于子类加载器之上:

          Bootstrap
              |
           System
              |
           Common
           /     
      Webapp1   Webapp2 ...

这些类加载器的特征,包括它们可见的类和资源的来源,将在下一节中详细讨论。

类加载器定义

如上图所示,Tomcat在初始化时创建以下类加载器:

Bootstrap - 此类加载器包含Java虚拟机提供的基本运行时类,以及System Extensions目录($JAVA_HOME/jre/lib/ext)中存在的JAR文件中的任何类。 注意:一些JVM可能将其实现为多个类加载器,或者它可能根本不可见(作为类加载器)。

System - 此类加载器通常从CLASSPATH环境变量的内容初始化。Tomcat内部类和Web应用程序都可以看到所有这些类。但是,标准的Tomcat启动脚本($CATALINA_HOME/bin/catalina.sh或 %CATALINA_HOME%bincatalina.bat)完全忽略CLASSPATH环境变量本身的内容,而是从以下存储库构建System类加载器:

$CATALINA_HOME/bin/bootstrap.jar - 包含用于初始化 Tomcat 服务器的main() 方法,以及它依赖的类加载器实现类。

$CATALINA_BASE/bin/tomcat-juli.jar 或 $CATALINA_HOME/bin/tomcat-juli.jar - 记录实现类。其中包括java.util.loggingAPI 的增强类 ,称为Tomcat JULI,以及Tomcat内部使用的Apache Commons Logging库的软件包重命名副本。有关详细信息,请参阅日志记录

如果tomcat-juli.jar是出现在 $CATALINA_BASE/bin 中,它被用来代替 $CATALINA_HOME/bin 中的那一个。它在某些日志记录配置中很有用

$CATALINA_HOME/bin/commons-daemon.jar - 来自Apache Commons Daemon项目的类。这个JAR文件不存在于CLASSPATH 由脚本catalina.bat|.sh 构建,但是从bootstrap.jar的清单文件中引用。

Common - 此类加载器包含对Tomcat内部类和所有Web应用程序都可见的其他类。

通常情况下,应用类应该不 放在这里。此类由common.loader加载器搜索的位置$CATALINA_BASE/conf/catalina.properties 中的属性定义。默认设置将按列出的顺序搜索以下位置:

解压缩的类和资源 $CATALINA_BASE/lib

JAR文件 $CATALINA_BASE/lib

解压缩的类和资源 $CATALINA_HOME/lib

JAR文件 $CATALINA_HOME/lib

默认情况下,这包括以下内容:

annotations-api.jar - JavaEE注释类。
catalina.jar - Tomcat的Catalina servlet容器部分的实现。
catalina-ant.jar - Tomcat Catalina Ant任务。
catalina-ha.jar - 高可用性包。
catalina-tribes.jar - 群组通信包。
ecj - * .jar - Eclipse JDT Java编译器。
el-api.jar - EL 2.2 API。
jasper.jar - Tomcat Jasper JSP编译器和运行时。
jasper-el.jar - Tomcat Jasper EL实现。
jsp-api.jar - JSP 2.2 API。
servlet-api.jar - Servlet 3.0 API。
tomcat-api.jar - Tomcat定义的几个接口。
tomcat-coyote.jar - Tomcat连接器和实用程序类。
tomcat-dbcp.jar - 基于包重命名的Apache Commons Pool和Apache Commons DBCP 1.x的数据库连接池实现。
tomcat-i18n - **。jar - 包含其他语言资源包的可选JAR。由于默认捆绑包也包含在每个多带带的JAR中,因此如果不需要消息的国际化,则可以安全地删除它们。
tomcat-jdbc.jar - 另一种数据库连接池实现,称为Tomcat JDBC池。有关详细信息,请参阅 文档
tomcat-util.jar - Apache Tomcat的各种组件使用的公共类。
tomcat7-websocket.jar - WebSocket 1.1实现
websocket-api.jar - WebSocket 1.1 API
WebappX - 为部署在单个Tomcat实例中的每个Web应用程序创建一个类加载器。/WEB-INF/classesWeb应用程序目录中的所有解压缩的类和资源,以及Web应用程序/WEB-INF/lib目录下的JAR文件中的类和资源,都对此Web应用程序可见,但对其他应用程序不可见。

如上所述,Web应用程序类加载器与默认Java委托模型不同(根据Servlet规范2.4版,第9.7.2节Web应用程序类加载器中的建议)。当加载从Web应用程序的一个类的请求WebappX被处理的类加载器,这个类加载器会在本地资源库第一而不是在寻找之前委托。也有例外。作为JRE基类的一部分的类不能被覆盖。对于某些类(例如J2SE 1.4+中的XML解析器组件),Java认可的功能可以用于Java 8.最后,类加载器将明确忽略包含Servlet API类的任何JAR文件 - 不包括此类Web应用程序中的JAR。Tomcat中的所有其他类加载器都遵循通常的委托模式。

因此,从Web应用程序的角度来看,类或资源加载按以下顺序查找以下存储库:

JVM的Bootstrap类

/WEB-INF/classes 您的Web应用程序的类

/WEB-INF/lib/*.jar 您的Web应用程序Jar 包

System 类加载器类(如上所述)

Common 类加载器类(如上所述)

如果配置了Web应用程序类加载器 , 则清单顺序变为:

JVM的Bootstrap类

System 类加载器类(如上所述)

Common 的类加载器类(如上所述)

/WEB-INF/classes 您的Web应用程序的类

/WEB-INF/lib/*.jar 您的Web应用程序的Jar 包

XML分析器和Java

从Java 1.4开始,JRE中包含一个JAXP API和一个XML解析器。这会对希望使用自己的XML解析器的应用程序产生影响。

在旧版本的Tomcat中,您只需替换Tomcat库目录中的XML解析器即可更改所有Web应用程序使用的解析器。但是,当您运行现代版本的 Java 时,此技术将无效,因为通常的类加载器委派过程将始终在JDK中选择优先于此实现的实现。

Java支持一种称为“支持标准覆盖机制”的机制,以允许替换在JCP外部创建的API(即来自W3C的DOM和SAX)。它还可用于更新XML解析器实现。有关更多信息,请参阅: http: //docs.oracle.com/javase/1.5.0/docs/guide/standards/index.html。

Tomcat通过-Djava.endorsed.dirs=$JAVA_ENDORSED_DIRS 在启动容器的命令行中包含系统属性设置来利用此机制 。此选项的默认值为 $CATALINA_HOME/endorsed。默认情况下不会创建此已签名的目录。请注意,Java 9不再支持已认可的功能,并且只有在目录$CATALINA_HOME/endorsed 存在或 JAVA_ENDORSED_DIRS 已设置变量 时才会设置上述系统属性。

请注意,覆盖任何JRE组件都存在风险。如果覆盖组件未提供100%兼容的API(例如,Xerces提供的API与JRE提供的XML API不完全兼容),则存在Tomcat和/或部署的应用程序将出现错误的风险。

在安全管理器下运行

在安全管理器下运行时,允许加载类的位置也取决于策略文件的内容。有关详细信息,请参阅安全管理器HOW-TO。

高级配置

还可以配置更复杂的类加载器层次结构。见下图。默认情况下, 未定义 Server 和 Shared 类加载器,并使用上面显示的简化层次结构。可以通过定义 server.loader 和/或 shared.loader 属性的值来使用这种更复杂的层次结构 conf/catalina.properties

      Bootstrap
          |
        System
          |
        Common
         /  
    Server  Shared
             /  
       Webapp1  Webapp2 ...

该服务器类加载器是唯一到Tomcat内部可见,并且是Web应用程序完全不可见。

所述 Common 类加载器是将所有的web应用程序可见,并且可以在所有的 web 应用程序被用来共享代码。但是,对此共享代码的任何更新都需要重新启动Tomcat

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/77738.html

相关文章

  • java加载相关

    摘要:标准扩展类加载器,它负责加载或由系统变量指定位置中的类库加载到内存中。系统类加载器,它负责将类路径中的类库加载到内存。 类加载机制大家应该已经非常熟悉了,采取双亲委派机制,当加载一个类时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成加载任务,就成功返回;如果父类无法加载,才由自己加载。 双亲委派机制的作用:防止内存中出现多份相同的字节码。 其他规则:1.隐式加载:...

    el09xccxy 评论0 收藏0
  • Java基础-加载器以及加载机制

    摘要:以上文中的类的加载过程为例,它的加载器为系统类加载器。自定义加载器编写自定义加载器并不困难,只要继承抽象类并覆盖方法就行了。源码来自参考资料类加载机制与类加载器架构深入探讨类加载器 序 我是在关于Java的面试题里了解到类加载器的,在这之前从未想过Java里类是如何被加载、解析的,一直以为只要Import就好了。事实上Java类加载器是一块非常重要的内容,可以用在类层次划分、OSGi、...

    stefan 评论0 收藏0
  • TOMCAT源码阅读总结(1)-TOMCAT加载体系

    摘要:加载器之间父子关系不是通过类继承的方式,而是通过对象变量的方式,来实现的。调用的方法,将设置为所有的获取各个类加载器相应的资源配置文件这些是具体配置在配置文件中的。 摘要 一直以来想看一下tomcat的源码,可以从头到尾理解一遍在整个web请求的处理过程中,容器完成的功能,容器怎么把一个url的请求的处理递交给了servlet,容器的pipeline是怎么设计的,容器的filter怎么...

    ChanceWong 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<