当前位置: 首页 > 科技观察

Java类是如何加载到Tomcat中的?

时间:2023-03-13 16:41:38 科技观察

本文说到Tomcat的类加载机制,不得不说一下自己翻译学习Tomcat的初衷。之前实习的时候学过JavaMelody的源码,但是是Maven工程,和自己的web工程集成后不能直接调试。后来同事指点,直接把Java类复制到src就可以了。很纳闷....为什么优先的是src下的Java文件(编译后的类),而不是jar包里的类?既然了解了Tomcat的类加载机制,一切就这么简单了。1、JVM中的类加载并不是一次加载所有的文件,而是按需一步步加载。比如JVM启动时,通过不同的类加载器加载不同的类。当用户在自己的代码中需要一些额外的类时,通过加载机制将其加载到JVM中,并保存一段时间,以供经常使用。因此,使用哪个类加载器,在哪里加载类,是JVM中的重要知识。2、JVM类加载JVM类加载采用:父类委托机制,如下图所示:JVM包括集中式类加载器:BootStrapClassLoader引导类加载器ExtClassLoader扩展类加载器AppClassLoader应用类加载器CustomClassLoader用户自定义类加载器它们的区别也是上面解释了。需要注意的是,不同的类加载器加载的类是不同的,所以如果一个类被用户加载器1加载了,其他用户就不能使用了。JVM运行时,当用户需要加载某些类时,会按照以下步骤进行(父类委托机制):用户自己的类加载器将加载请求传递给父加载器,父加载器通过对其父加载器的加载请求,直到加载器树的顶层。最顶层的类加载器首先针对其特定位置进行加载,如果无法加载则交给子类。如果直到加载底层类才加载,那么会抛出异常ClassNotFoundException。所以按照这个过程可以想象,如果同一个类存放在CLASSPATH指定的目录和自己的工作目录下,那么CLASSPATH目录下的文件会被优先加载。3、Tomcat类加载Tomcat中类的加载略有不同,如下图:Tomcat启动时,会创建几个类加载器:1.Bootstrap引导类加载器加载JVM启动所需的类,以及作为标准扩展类(位于jre/lib/ext下)2.System类加载器加载Tomcat启动的类,如bootstrap.jar,通常在catalina.bat或catalina.sh中指定。位于CATALINA_HOME/bin下。3、通用通用类加载器加载Tomcat和通用应用程序使用的一些类,位于CATALINA_HOME/lib下,如servlet-api.jar4、webapp应用程序类加载器每个应用程序在部署后都会创建一个唯一的类加载器。类加载器会加载WEB-INF/lib下的jar文件中的class和WEB-INF/classes下的class文件。Tomcat的Server文件配置详解!本文推荐大家阅读。当应用程序需要某个类时,会按照以下顺序加载:使用bootstrap引导类加载器加载使用system系统类加载器加载使用应用程序类加载器在WEB-INF/classes中加载使用应用程序类loader加载加载器加载在WEB-INF/lib中使用普通的类加载器加载在CATALINA_HOME/lib中4.问题扩展通过上面Tomcat类加载机制的理解,就不难理解为什么要放置Java文件了Eclipse中src文件夹中jar包中的类会优先处理吗?这是因为在Tomcat启动时,Eclipse中src文件夹下的java文件和webContent中的JSP文件都会被编译成class文件放在WEB-INF/class下。Eclipse外部引用的jar包相当于放在WEB-INF/lib中。因此,必须首先加载从Java文件或JSP文件编译的类。通过这个,我们可以简单的将Java文件放在src文件夹下,对Java文件进行修改调试,这样我们就可以很方便的学习到有源代码Java文件但没有打包成xxx-source的jar包。此外,开发者也会因为粗心大意而犯下以下错误。CATALINA_HOME/lib和WEB-INF/lib中放置了不同版本的jar包,在某些情况下会导致类无法加载的错误。另外,如果多个应用程序使用同一个jar包文件,当放置多个副本时,可能会导致类无法在多个应用程序之间加载的错误。