Servlet类装载器

xiaoxiao2025-10-12  17

一.类装载器

Java虚拟机使用每一个类的第一件事情就是将类的字节码装载进来,装载类字节码是由类装载器完成的。类装载器首先将一个类转换成一个.class文件,然后读取文件的内容,.class文件的内容是utf-8编码的,转换成Unicode编码后装载入Java虚拟机,当一个类被加载后,Java虚拟机将其编译为可执行的代码存储在内存中,索引信息存储进HashTable中,索引关键字为类的完整名称,当Java虚拟机要使用某个类时,直接在这个HashTable中找,找不到则加载。加载一个类实际上实在创建一个Class的对象,这个对象封装的内存就是当前加载的类的字节码数据,有以下3种方式获得Class对象:

类名.class对象.getClassClass.forName("类名")

(1)类装载器本身也是一个Java类,所以需要被其他类装载器装载。最顶层的装载器为Bootstrap类装载器,它是用特定与操作系统的本地代码实现的,不用其余的装载器装载,它负责加载Java核心包的类。Java核心包的类有2个类装载器:ExtClassLoader和AppClassLoader。ExtClassLoader负责加载<JAVA_HOME>/jre/lib/ext目录下的类,AppClassLoader负责加载应用程序的启动执行类。

(2)一个类装载器实例化时必须指定一个父装载器,如果不指定。则以ClassLoader.getSystemClassLoader()方法返回的系统类装载器为父装载器,通常设置为AppClassLoader,是在第一次使用getSystemClassLoader()时设置的,调用发生在应用程序启动的早期阶段。可以通过java.system.class.loader来设置为其他类装载器。ExtClassLoader是AppClassLoader的父级类装载器,自身没有父级类装载器。每个装载器只能装载特定目录的类,但ClassLoader是一种委托模式装载的,子装载器可以调用父装载器去装载类,一直到追溯到没有父级类装载器为止,则使用Java虚拟机的BootStarp装载器装载。若父装载器无法装载,则一级一级返回,如果最底层子装载器无法装载,则报告ClassNotFoundException。一个类装载器只能创建某一个类的一个Class对象,但每个类装载器存在不同的名称和空间,可以分别给同一个类创建出Class对象,但这些Class对象没有任何关联。采用委托模式可以避免这种情况发生。

(3)如果在A类对象中New了B类对象,则Java虚拟机使用加载A类的加载器加载B类。如果使用Class.forName加载,可以指定类加载,如果没有指定,则为加载当前类的加载器加载。

(4)每个运行的线程都有一个关联的上下文类装载器。可以使用Thread.setContextClassLoader()方法设置上下文类加载器,默认为其父线程的上下文类加载器。主线程的类加载器初始化为ClassLoader.getSystemClassLoader()返回的加载器。一样采用委托模式加载,如果父加载器无法加载,则自己进行加载。

2.Tomcat中的类装载器

类装载器的父子关系图如下:

(1)Bootstrap是虚拟机内嵌的装载器和ExtClassLoader的总称(2)System通常为AppClassLoader,加载CLASSPATH环境变量中的类(3)Commen加载<CATALINA_HOME>/commen/classes和<CATALINA_HOME>/commen/lib中的类,对Tomcat服务内核和每个Web应用程序都可见(4)Catalina负责<CATALINA_HOME>/server/classes和<CATALINA_HOME>/server/lib,只对Tomcat服务器内核可见(5)Shared负责<CATALINA_HOME>/share/classes和<CATALINA_HOME>/share/lib,对所有Web程序可见,对Tomcat内核不可见(6)Webapp负责当前Web程序/Web-INF/classes中的.class文件和/Web-INF/lib中的jar包,只对当前Web程序可见。  

 

转载请注明原文地址: https://www.6miu.com/read-5037788.html

最新回复(0)