`
xiaoyaocao
  • 浏览: 276087 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

tomcat5启动说servlet-jsp.jar not loaded 说明

 
阅读更多
一. Class Loader(类装载器)
1. 类装载器结构
类装载器(Class Loader)是Java虚拟机的组成部分之一,如图1所示.Java虚拟机有两种类装载器:启动类装载器和用户自定义类装载器.
URL:http://blog.blogchina.com/upload/2004-11-24/20041124104254943028.jpg

图1:Java虚拟机的内部体系结构.
启动类装载器 每个Java虚拟机实现都必须有一个启动类装载器.在Sun的JDK 1.2以后的版本中,启动类装载器只负责在系统类(核心Java API的class文件)的安装路径中查找要装入的类.
用户自定义类装载器 它是普通的Java对象,它的类必须继承自java.lang.ClassLoader类.在Sun的JDK 1.2以后的版本中,用户自定义类装载器负责核心Java API以外的其它class文件的装载.例如,用于安装或下载标准扩展的class文件,在类路径中发现的类库的class文件,用于应用程序运行的class文件,等等.
命名空间 Java虚拟机为每一个类装载器维护一个唯一标识的命名空间.一个Java程序可以多次装载具有同一个全限定名(指类所属的包名加类名,如java.lang.Object就是类Object的全限定名)的多个类(class). Java虚拟机要确定这"多个类"的唯一性,因此,当多个类装载器都装载了同名的类时,为了唯一地标识这个类,还要在类名前加上装载该类的类装载器的标识(指出了类所位于的命名空间).例如:ExtClassLoader 装载了sun.text.resources.DateFormatZoneData_zh_CN类,AppClassLoader装载了sun.text.resources.DateFormatZoneData_zh_HK类, Java虚拟机就认为这两个类位于不同的包中,彼此之间不能访问私有成员.如果AppClassLoader也装载了sun.text.resources.DateFormatZoneData_zh_CN类, 虽然"类名"相同,Java虚拟机也认为它们是不同的类,因为它们处在不同的命名空间中.
2. 委托(Delegation)模型
当Java虚拟机开始运行时,在应用程序开始启动以前,它至少创建一个用户自定义装载器,也可能创建多个.所有这些装载器被连接在一个Parent-Child的委托链中,在这个链的顶端是启动类装载器,末端是被称为"系统类装载器"的类装载器.
例如,假设你写了一个应用程序,在虚拟机上运行它.虚拟机在启动时实例化了两个用户自定义类装载器:一个"扩展类装载器",一个"类路径类装载器".这些类装载器和启动类装载器一起联入一个Parent-Child委托链中,如图2所示.
URL:http://blog.blogchina.com/upload/2004-11-24/2004112410430176267.jpg

图2arent-Child类装载器委托链
类路径类装载器的Parent是扩展类装载器, 扩展类装载器的Parent是启动类装载器.在图2中,类路径类装载器就被实例为系统类装载器.假设你的程序实例化它的网络类装载器,它就指明了系统类装载器作为它的Parent.
下面的例程说明了类装载器的父子关系.
例程1:
package test;
import java.net.URL;
import java.net.URLClassLoader;
public class ClassLoaderTest {
private static int count = -1;
public static void testClassLoader(Object obj) {
if (count < 0 && obj == null) {
System.out.println("Input object is NULL";
return;
}
ClassLoader cl = null;
if (obj != null && !(obj instanceof ClassLoader)) {
cl = obj.getClass().getClassLoader();
} else if (obj != null) {
cl = (ClassLoader) obj;
}
count++;
String parent = "";
for (int i = 0; i < count; i++) {
parent += "arent ";
}
if (cl != null) {
System.out.println(
parent + "ClassLoader name = " + cl.getClass().getName());
testClassLoader(cl.getParent());
} else {
System.out.println(
parent + "ClassLoader name = BootstrapClassLoader";
count = -1;
}
}
public static void main(String[] args) {
URL[] urls = new URL[1];
URLClassLoader urlLoader = new URLClassLoader(urls);
ClassLoaderTest.testClassLoader(urlLoader);
}
}
以上例程的输出为:
ClassLoader name = java.net.URLClassLoader
Parent ClassLoader name = sun.misc.Launcher$AppClassLoader
Parent Parent ClassLoader name = sun.misc.Launcher$ExtClassLoader
Parent Parent Parent ClassLoader name = BootstrapClassLoader
类装载器请求过程
以上例程1为例.将main方法改为:
ClassLoaderTest tc = new ClassLoaderTest();
ClassLoaderTest.testClassLoader(tc);
输出为:
ClassLoader name = sun.misc.Launcher$AppClassLoader
Parent ClassLoader name = sun.misc.Launcher$ExtClassLoader
Parent Parent ClassLoader name = BootstrapClassLoader
程序运行过程中,类路径类装载器发出一个装载ClassLoaderTest类的请求, 类路径类装载器必须首先询问它的Parent---扩展类装载器---来查找并装载这个类,同样扩展类装载器首先询问启动类装载器.由于ClassLoaderTest不是Java API(JAVA_HOME/jre/lib)中的类,也不在已安装扩展路径(JAVA_HOME/jre/lib/ext)上,这两类装载器都将返回而不会提供一个名为ClassLoaderTest的已装载类给类路径类装载器.类路径类装载器只能以它自己的方式来装载ClassLoaderTest,它会从当前类路径上下载这个类.这样,ClassLoaderTest就可以在应用程序后面的执行中发挥作用.
在上例中, ClassLoaderTest类的testClassLoader方法被首次调用,该方法引用了Java API中的类java.lang.String.Java虚拟机会请求装载ClassLoaderTest类的类路径类装载器来装载java.lang.String.就像前面一样,类路径类装载器首先将请求传递给它的Parent类装载器,然后这个请求一路被委托到启动类装载器.但是,启动类装载器可以将java.lang.String类返回给类路径类装载器,因为它可以找到这个类,这样扩展类装载器就不必在已安装扩展路径中查找这个类,类路径类装载器也不必在类路径中查找这个类.扩展类装载器和类路径类装载器仅需要返回由启动类装载器返回的类java.lang.String.从这一刻开始,不管何时ClassLoaderTest类引用了名为java.lang.String的类,虚拟机就可以直接使用这个java.lang.String类了.
在上述过程中也可能会发生错误,在本文下面的例子中将会涉及.
3. 装载 连接及初始化
在一个Java类的生命周期中,装载,连接和初始化只是其开始阶段.只有开始阶段结束以后,类才可以被实例化并被使用.整个开始阶段必须按以下顺序进行:
1)装载 把二进制形式的Java class读入虚拟机中.
2)连接 把已经读入虚拟机的二进制形式的类数据合并到虚拟机的运行状态中去.连接阶段分为验证,准备和解析三个子步骤.
3)初始化 给类变量赋以适当的初始值.
Java虚拟机允许类装载器(启动或用户自定义类装载器)缓存Java class的二进制形式,在预知某个类将要被使用时就装载它.如果一个类装载器在预先装载时遇到问题,它应该在该类被"首次主动使用"时报告该问题(通过抛出一个java.lang.LinkageError的子类).也就是说,如果一个类装载器在预先装载时遇到缺失或错误的class文件,它必须等到程序首次被主动使用该类时才报告错误.如果这个类一直没有被程序主动使用,那么该类装载器将不会报告错误.
二.Tomcat5中的Class Loader
当Tomcat5启动的时候,它会首先创建一组class loader,如commonLoader, sharedLoader, catalinaLoader,webappLoader等.其委托模型如下图3所示:
Bootstrap
|
System
|
Common
/ /
Catalina Shared
/
Webapp1 ...
图3:Tomcat5类装载器委托模型
其中,
1) Bootstrap 该类装载器装载JAVA_HOME/jre/lib和JAVA_HOME/jre/lib/ext两目录上的JAR包.
2) System 该类装载器装载当前CLASSPATH上的JAR包.在Windows系统下, CLASSPATH环境变量会在CATALINA_HOME/bin/setclasspath.bat和CATALINA_HOME/bin/catalina.bat文件中被重新设置.
3) Common 该类装载器装载CATALINA_HOME/common/classes目录中的类, CATALINA_HOME/commons/endorsed和CATALINA_HOME/common/lib目录中的JAR包.
4) Catalina 该类装载器装载CATALINA_HOME/server/classes和CATALINA_HOME/server/lib目录中的类和JAR包.
5) Shared 该类装载器装载CATALINA_HOME/shared/classes和CATALINA_HOME/shared/lib目录中的类和JAR包.
6) WebappX 该类装载器装载WEB-INF/classes和WEB-INF/lib目录中的类和JAR包.

需要补充说明的是,WebappX类装载器独立于上文提到的Java2的委托模型.当WebappX类装载器装载一个类时,它会首先查找本身所辖目录(即WEB-INF/classes和WEB-INF/lib)下的类,而不会启动委托机制.当然对于Bootstrap和System类装载器中存在的类,是要进行委托的.另外,对于下面这些包中的类,如:
javax.*
org.xml.sax.*
org.w3c.dom.*
org.apache.xerces.*
org.apache.xalan.*
WebappX类装载器装载时也要启动委托机制.
例如,假设ojdbc14.jar处在setclasspath.bat中的CLASSPATH下,同时也处在WEB-INF/lib目录下.类装载器系统在请求装载oracle.jdbc.driver.OracleDriver类时,会得到从System类装载器返回的类,而不是WebappX类装载器.
再假设ojdbc14.jar处在CATALINA_HOME/common/lib和WEB-INF/lib目录下,而没有处在setclasspath.bat中的CLASSPATH下,那么类装载器系统就会得到从WebappX类装载器返回的类,而不是Common类装载器.
另外,如果WEB-INF/lib目录下存在包含有servlet API类的JAR包,该JAR包将会被WebappX类装载器忽略.例如,
考虑到应用程序的编译问题,你可能会把servlet-api.jar包Copy到应用程序中的WEB-INF/lib目录下.那么,在Tomcat5启动时,启动屏幕上就会出现如下输出:
2004/09/12 14:53:57 org.apache.catalina.loader.WebappClassLoader validateJarFile
情报: validateJarFile(E:/MyData/myProjects/MyBS_SQL/web/WEB-INF/lib/servlet-api.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class
上述信息并不影响你的程序运行.因为WebappX类装载器虽然会忽略掉WEB-INF/lib目录下servlet-api.jar包,但是,Common类装载器已经装载了servlet-api.jar包.如前所述,对于javax.*中的类, WebappX类装载器是要启动委托机制的,所以WebappX类装载器会得到Common类装载器返回的javax.*中的类.
如果不希望Tomcat5启动时输出上述信息,只需将servlet-api.jar包从应用程序中的WEB-INF/lib目录下移走就行了.
总结一下,Tomcat5类装载器系统在请求装载一个类时,它以下面列举的顺序进行:
· Bootstrap (JAVA_HOME/jre/lib和JAVA_HOME/jre/lib/ext)
· System (当前CLASSPATH上)
· /WEB-INF/classes 和/WEB-INF/lib/*.jar
· CATALINA_HOME/common/classes
· CATALINA_HOME/common/endorsed/*.jar
· CATALINA_HOME/common/lib/*.jar
· CATALINA_HOME/shared/classes 和CATALINA_HOME/shared/lib/*.jar
分享到:
评论

相关推荐

    tomcat-embed-core-9.0.16.jar

    tomcat-embed-core-9.0.16

    servlet-api.jar

    编写servlet要用到HttpServletRequest和HttpServletResponse等对象,这些对象都是要靠这个jar包才能使用的(jar not loaded )。 在Eclipse中添加Servlet-api.jar的方法 :窗口-&gt;首选项-&gt;java -&gt; 已安装的jre -&gt; ...

    geronimo-servlet_2.5_spec-1.2.jar

    geronimo-servlet_2.5_spec-1.2.jar geronimo-servlet_2.5_spec-1.2.jar

    jaxb-api-2.1.jar

    在使用webservice,esb等需要jaxb的项目里经常会出现 JAXB 2.0 API is being loaded from the bootstrap classloader错误.执行System.out.println(System.getProperty("java.endorsed.dirs"));输出jaxb-api-2.1.jar...

    ojdbc6.jar ojdbc6-11.2.jar

    使用logstash连接oracle的时候必须使用匹配ojdbc,不然会报错Java:oracle.jdbc.driver.OracleDriver not loaded. Are you sure you've included the correct jdbc driver in :jdbc_driver_library? 一个是oracle11.1....

    spring项目jar包2

    5. **XMLBeans**: `xmlbeans-2.6.0.jar`是一个处理XML的Java库,它将XML Schema转化为Java类,使得Java程序可以直接操作XML文档,提高了处理XML数据的效率和便利性。 6. **SQLite JDBC驱动**: `sqlite-jdbc-3.7.15-...

    springloaded-1.2.8.RELEASE

    SpringLoaded是Spring Boot开发过程中的一款重要工具,它主要用于...总的来说,"springloaded-1.2.8.RELEASE"是Spring Boot开发者的一个得力助手,通过理解和掌握它的使用,可以显著提高开发效率,让开发过程更加流畅。

    instantclient-basic-windows.x64-12.1.0.2.0 解决Navicat 15 64位 连Oracle 11.2.0.4

    适合最新Navicate 15 64位使用,解决连接Oracle 11g 64位时 Oracle library is not loaded,经测试instantclient-basic-windows.x64-11.2.0.4.0死活连接不上 不要被误导。换12.1完美解决。 32位的navicate 可以用...

    springloaded-1.2.5.RELEASE.jar

    springloaded-1.2.5.RELEASE.jar

    libsigar-amd64-linux.so以及libsigar-x86-linux.so

    5. **文件系统信息**:获取磁盘空间使用情况、I/O统计和文件系统类型。 6. **系统负载**:测量系统的整体负载,了解系统当前的繁忙程度。 7. **硬件信息**:识别系统上的硬件组件,如CPU型号、内存大小等。 通过...

    instantclient-basic-windows.x64-12.2.0.1.0.rar

    Navicat Premium 12是一款强大的数据库管理工具,支持多种数据库类型,包括Oracle,当尝试连接到Oracle数据库时,如果遇到“oracle library is not loaded”的错误,通常是因为缺少了Oracle Instant Client。...

    springloaded-1.2.8.RELEASE.jar

    springloaded-1.2.8.jar 拿去不谢。。。。。。。。。。。。。。。。。

    junit-jupiter-5.7.0.jar

    junit-jupiter-5.7.0.jar

    netty-transport-native-epoll-4.1.36.Final-linux-x86_64.jar

    java运行依赖jar包

    解决php-fpm.service not found问题的办法

    本文给大家详细介绍了解决php-fpm.service not found问题的相关内容,文中介绍的非常详细,下面来一起看看详细的介绍: 环境介绍 环境:ubuntu 16.04 64 php 版本:php-7.1.4 发现问题 正常编译安装 php 按照以前...

    xterm-addon-attach.js

    xterm-addon-attach.js

    PHP-7.4.29.tar.gz及oniguruma-6.9.tar.gz缺失依赖包安装解决

    安装PHP-7.4.29.tar.gz时,报错缺少oniguruma,yum -y install oniguruma-devel安装后仍然报错,rpm -e oniguruma删除后,重新yum install -y oniguruma-devel还是报错,缺少oniguruma。重新安装oniguruma-6.9.tar....

    MariaDB环境包,安装MariaDB出现错误:Failed to start mariadb.service: Unit not found。

    perl-Net-Daemon-0.48-5.el7.noarch.rpm perl-PlRPC-0.2020-14.el7.noarch.rpm 1 yum install boost-program-options-1.53.0-27.el7.x86_64.rpm 2 yum install galera-4-26.4.2-1.rhel7.el7.centos.x86_64.rpm ...

    ruby selenium-client-1.2.18.gem

    4. command prompt go to –&gt; C:\selenium-remote-control-1.0.3\selenium-server-1.0.3&gt;java -jar selenium-server.jar 5. Download the RubyInstaller– The Ruby Installer is currently available only for the ...

Global site tag (gtag.js) - Google Analytics