1 基本信息
摘要:分别介绍Tomcat和Webshpher类加载机制。
作者:戴小丹 林晓咏
2 Tomcat类加载机制
Tomcat Server在启动的时候将构造一个ClassLoader树,以保证模块的类库是私有的
Tomcat Server的ClassLoader结构图如下:
- Bootstrap - 载入JVM自带的类和/jre/lib/ext/*.jar
- System - 载入/*.class
- Common - 载入/common/...,它们对TOMCAT和所有的WEB APP都可见
- Catalina - 载入/server/...,它们仅对TOMCAT可见,对所有的WEB APP都不可见
- Shared - 载入/shared/...,它们仅对所有WEB APP可见,对TOMCAT不可见(也不必见)
- WebApp - 载入ContextBase?/WEB-INF/...,它们仅对该WEB APP可见
每个运行中的线程都有一个成员contextClassLoader,用来在运行时动态地载入其它类,系统默认的 contextClassLoader是systemClassLoader,所以一般而言java程序在执行时可以使用JVM自带的类、$ JAVA_HOME/jre/lib/ext/中的类和/中的类,可以使用Thread.currentThread(). setContextClassLoader(...);更改当前线程的contextClassLoader,来改变其载入类的行为ClassLoader被组织成树形,一般的工作原理是:
1) 线程需要用到某个类,于是contextClassLoader被请求来载入该类
2) contextClassLoader请求它的父ClassLoader来完成该载入请求
3) 如果父ClassLoader无法载入类,则contextClassLoader试图自己来载入
3 Websphere类加载机制
Java应用程序运行时,在class执行和被访问之前,它必须通过类加载器加载使之有效,类加载器是JVM代码的一部分,负责在JVM虚拟机中查找和加载所有的Java 类和本地的lib库。类加载器的不同配置影响到应用程序部署到应用程序服务器上运行时的行为。JVM和WebSphere应用程序服务器提供了多种不同的类加载器配置, 形成一个具有父子关系的分层结构。
WebSphere中类加载器的层次结构图1所示:
如上图所示,WebSphere中类加载器被组织成一个自上而下的层次结构,最上层是系统的运行环境JVM,最下层是具体的应用程序,上下层之间形成父子关系。
JVM Class loader:位于整个层次结构的最上层,它是整个类加载器层次结构的根,因此它没有父类加载器。这个类加载器负责加载JVM类, JVM 扩展类,以及定义在classpath 环境变量上的所有的Java类。
WebSphere Extensions Class loader:WebSphere 扩展类加载器, 它将加载WebSphere的一些runtime 类,资源适配器类等。
WebSphere lib/app Class loader:WebSphere服务器类加载器,它将加载WebSphere安装目录下$(WAS_HOME)/lib/app路径上的类。 在WAS v4版本中,WAS使用这个路径在所有的应用程序之间共享jar包。从WAS v5开始, 共享库功能提供了一种更好的方式,因此,这个类加载器主要用于一些原有的系统的兼容。
WebSphere "server" Class loader:WebSphere应用服务器类加载器。 它定义在这个服务器上的所有的应用程序之间共享的类。WAS v5中有了共享库的概念之后,可以为应用服务器定义多个与共享库相关联的类加载器,他们按照定义的先后顺序形成父子关系。
Application Module Class Loader:应用程序类加载器,位于层次结构的最后一层,用于加载J2EE应用程序。根据应用程序的类加载策略的不同,还可以为Web模块定义自己的类加载器。
关于WebSphere的类加载器的层次结构,以下的几点说明可能更有助于进一步的理解类的查找和加载过程:
每个类加载器负责在自身定义的类路径上进行查找和加载类。
一个子类加载器能够委托它的父类加载器查找和加载类,一个加载类的请求会从子类加载器发送到父类加载器,但是从来不会从父类加载器发送到子类加载器。
一旦一个类被成功加载,JVM 会缓存这个类直至其生命周期结束,并把它和相应的类加载器关联在一起,这意味着不同的类加载器可以加载相同名字的类。
如果一个加载的类依赖于另一个或一些类,那么这些被依赖的类必须存在于这个类的类加载器查找路径上,或者父类加载器查找路径上。
如果一个类加载器以及它所有的父类加载器都无法找到所需的类,系统就会抛出ClassNotFoundExecption异常或者NoClassDefFoundError的错误。
类加载器的委托模式
类加载器有一个重要的属性:委托模式(Delegation Mode,有时也称为加载方式:Classloader mode)。委托模式决定了类加载器在查找一个类的时候,是先查找类加载器自身指定的类路径还是先查找父类加载器上的类路径。
类加载器的委托模式有两个取值:
Parent_First:在加载类的时候,在从类加载器自身的类路径上查找加载类之前,首先尝试在父类加载器的类路径上查找和加载类。
Parent_Last:在加载类的时候,首先尝试从自己的类路径上查找加载类,在找不到的情况下,再尝试父类加载器类路径。
有了委托模式的概念,我们可以更加灵活的配置在类加载器的层次结构中类的加载和查找方式。表1中给出了在WebSphere的类加载器层次结构中各个类加载器的委托模式的定义,并给出了不同的类加载器内类的生命周期。
注意:在上表中,"JVM Class loader" 因为在类加载器的最顶层,它没有父类加载器,因此其委托模式为N/A,"WebSphere Extensions Class loader"和"WebSphere lib/app Class loader"的委托模式固定为表中的取值,不可配置,其它的类加载器的委托模式都是可以配置的。
WebSphere中的类加载器策略
WebSphere中对类加载器有一些相关的配置,称为类加载器策略(class loader policy)。类加载器策略指类加载器的独立策略(class loader isolation policy),通过类加载器策略设置,我们可以为WAS和应用程序的类加载器进行独立定义。
每个WAS可以配置自己的应用程序类加载器策略,WAS中的每个应用程序也可以配置自己的Web模块类加载器策略,下面我们对这两种策略分别介绍。
1.应用服务器(WAS)配置:应用程序类加载器策略
应用服务器对应用程序类加载器策略有两种配置:
Single:整个应用服务器上的所有应用程序使用同一个类加载器。在这种配置下,每个应用程序不再有自己的类加载器。
Multiple:应用服务器上的每个应用程序使用自己的类加载器。
2.应用程序配置:Web模块类加载器策略
应用程序中对Web模块类加载器有两种配置:
Application:整个应用程序内的所有的实用程序jar包和Web模块使用同一个类加载器。
Module:应用程序内的每个Web模块使用自己的类加载器。应用程序的类加载器仍然存在,负责加载应用程序中Web模块以外的其它类,包括所有的实用程序jar包。
从上面的定义可以看出,不同的类加载器策略的配置下,类加载器的层次结构上的某些类加载器可能不存在。比如在应用程序服务器的应用程序类加载器策略定义为single的情况下,应用程序的类加载器将不存在,同一个应用服务器上的所有应用程序将共用同一个类加载器,这也就意味着不同的应用程序之间的类是共享的,应用程序间不能存在同名的类。
4 Jboss启动及加载过程
详细参考:http://tech.it168.com/j/2007-06-27/200706271521984.shtml
1) org.jboss.Main.main(String[]) 为入口.
2) main 函数创建一个名叫”jboss”的线程组, 然后创建一个属于该组的线程, 在线程中执行boot方法.
3) boot 方法首先处理main函数中的参数(及一些其它的系统环境设置), 接着就用系统的属性创建了org.jboss.system.server.ServerLoader实例[new ServerLoader(props)].
4) ServerLoader 注册Jboss相关的类路径, 包括XML解析器, jboss-jmx.jar, concurrent.jar及其它的一些额外的类路径.
5) ServerLoader 通过load(ClassLoader)方法创建Jboss Server实例. 参数ClassLoader是ClassLoader parentCL = Thread.currentThread(). getContextClassLoader( )得到的当前线程的类加载器. 创建的Server实例是org.jboss.system.server.Server接口的实现. load(ClassLoader)方法的细节:
Ø 用jar包及在ServerLoader中注册的类路径创建一个URLClassLoader的实例, 把传入的ClassLoader作为该URLClassLoader的parent.
Ø Server 接口的实现类由系统属性 jboss.server.type决定, 默认是 org.jboss.system.server.ServerImpl.
Ø URLClassLoader 通过无参构造函数加载Server接口实现的实例. 在加载前把当前线程的类加载器置为该URLClassLoader, 在加载完成后再置回之前传入的ClassLoader.
6) Server 实例用系统属性进行初始化[server.init(props)].
7) 服务起动[server.start()]. 起动过程的默认实现如下:
Ø 把当前线程类型加载器置为加载该Server接口实现实例的ClassLoader.
Ø 在jboss域内, 通过MBeanServerFactory的createMBeanServer(String)方法创建MbeanServer实例.
Ø 在MBean Server上注册ServerImpl和ServerConfigImpl两个MBean.
Ø 初始化统一的类加载仓库(unified class loader repository), 用来装载服务器配置目录及其它可选目录下的jar文件. 对于每一个jar文件和类目录都会创建一个相应的org.jboss.jmx.loading.UnifiedClassLoader实例, 并且注册到统一的仓库中. 其中一个UnifiedClassLoader实例会被设置为当前线程上下文的ClassLoader. [?: This effectively makes allUnifiedClassLoaders available through the thread context class loader.]
Ø 接下来创建org.jboss.system.ServiceController的MBean实例. ServiceController管理JBoss MBean服务的生命周期.
摘要:分别介绍Tomcat和Webshpher类加载机制。
作者:戴小丹 林晓咏
2 Tomcat类加载机制
Tomcat Server在启动的时候将构造一个ClassLoader树,以保证模块的类库是私有的
Tomcat Server的ClassLoader结构图如下:
- Bootstrap - 载入JVM自带的类和/jre/lib/ext/*.jar
- System - 载入/*.class
- Common - 载入/common/...,它们对TOMCAT和所有的WEB APP都可见
- Catalina - 载入/server/...,它们仅对TOMCAT可见,对所有的WEB APP都不可见
- Shared - 载入/shared/...,它们仅对所有WEB APP可见,对TOMCAT不可见(也不必见)
- WebApp - 载入ContextBase?/WEB-INF/...,它们仅对该WEB APP可见
每个运行中的线程都有一个成员contextClassLoader,用来在运行时动态地载入其它类,系统默认的 contextClassLoader是systemClassLoader,所以一般而言java程序在执行时可以使用JVM自带的类、$ JAVA_HOME/jre/lib/ext/中的类和/中的类,可以使用Thread.currentThread(). setContextClassLoader(...);更改当前线程的contextClassLoader,来改变其载入类的行为ClassLoader被组织成树形,一般的工作原理是:
1) 线程需要用到某个类,于是contextClassLoader被请求来载入该类
2) contextClassLoader请求它的父ClassLoader来完成该载入请求
3) 如果父ClassLoader无法载入类,则contextClassLoader试图自己来载入
3 Websphere类加载机制
Java应用程序运行时,在class执行和被访问之前,它必须通过类加载器加载使之有效,类加载器是JVM代码的一部分,负责在JVM虚拟机中查找和加载所有的Java 类和本地的lib库。类加载器的不同配置影响到应用程序部署到应用程序服务器上运行时的行为。JVM和WebSphere应用程序服务器提供了多种不同的类加载器配置, 形成一个具有父子关系的分层结构。
WebSphere中类加载器的层次结构图1所示:
如上图所示,WebSphere中类加载器被组织成一个自上而下的层次结构,最上层是系统的运行环境JVM,最下层是具体的应用程序,上下层之间形成父子关系。
JVM Class loader:位于整个层次结构的最上层,它是整个类加载器层次结构的根,因此它没有父类加载器。这个类加载器负责加载JVM类, JVM 扩展类,以及定义在classpath 环境变量上的所有的Java类。
WebSphere Extensions Class loader:WebSphere 扩展类加载器, 它将加载WebSphere的一些runtime 类,资源适配器类等。
WebSphere lib/app Class loader:WebSphere服务器类加载器,它将加载WebSphere安装目录下$(WAS_HOME)/lib/app路径上的类。 在WAS v4版本中,WAS使用这个路径在所有的应用程序之间共享jar包。从WAS v5开始, 共享库功能提供了一种更好的方式,因此,这个类加载器主要用于一些原有的系统的兼容。
WebSphere "server" Class loader:WebSphere应用服务器类加载器。 它定义在这个服务器上的所有的应用程序之间共享的类。WAS v5中有了共享库的概念之后,可以为应用服务器定义多个与共享库相关联的类加载器,他们按照定义的先后顺序形成父子关系。
Application Module Class Loader:应用程序类加载器,位于层次结构的最后一层,用于加载J2EE应用程序。根据应用程序的类加载策略的不同,还可以为Web模块定义自己的类加载器。
关于WebSphere的类加载器的层次结构,以下的几点说明可能更有助于进一步的理解类的查找和加载过程:
每个类加载器负责在自身定义的类路径上进行查找和加载类。
一个子类加载器能够委托它的父类加载器查找和加载类,一个加载类的请求会从子类加载器发送到父类加载器,但是从来不会从父类加载器发送到子类加载器。
一旦一个类被成功加载,JVM 会缓存这个类直至其生命周期结束,并把它和相应的类加载器关联在一起,这意味着不同的类加载器可以加载相同名字的类。
如果一个加载的类依赖于另一个或一些类,那么这些被依赖的类必须存在于这个类的类加载器查找路径上,或者父类加载器查找路径上。
如果一个类加载器以及它所有的父类加载器都无法找到所需的类,系统就会抛出ClassNotFoundExecption异常或者NoClassDefFoundError的错误。
类加载器的委托模式
类加载器有一个重要的属性:委托模式(Delegation Mode,有时也称为加载方式:Classloader mode)。委托模式决定了类加载器在查找一个类的时候,是先查找类加载器自身指定的类路径还是先查找父类加载器上的类路径。
类加载器的委托模式有两个取值:
Parent_First:在加载类的时候,在从类加载器自身的类路径上查找加载类之前,首先尝试在父类加载器的类路径上查找和加载类。
Parent_Last:在加载类的时候,首先尝试从自己的类路径上查找加载类,在找不到的情况下,再尝试父类加载器类路径。
有了委托模式的概念,我们可以更加灵活的配置在类加载器的层次结构中类的加载和查找方式。表1中给出了在WebSphere的类加载器层次结构中各个类加载器的委托模式的定义,并给出了不同的类加载器内类的生命周期。
注意:在上表中,"JVM Class loader" 因为在类加载器的最顶层,它没有父类加载器,因此其委托模式为N/A,"WebSphere Extensions Class loader"和"WebSphere lib/app Class loader"的委托模式固定为表中的取值,不可配置,其它的类加载器的委托模式都是可以配置的。
WebSphere中的类加载器策略
WebSphere中对类加载器有一些相关的配置,称为类加载器策略(class loader policy)。类加载器策略指类加载器的独立策略(class loader isolation policy),通过类加载器策略设置,我们可以为WAS和应用程序的类加载器进行独立定义。
每个WAS可以配置自己的应用程序类加载器策略,WAS中的每个应用程序也可以配置自己的Web模块类加载器策略,下面我们对这两种策略分别介绍。
1.应用服务器(WAS)配置:应用程序类加载器策略
应用服务器对应用程序类加载器策略有两种配置:
Single:整个应用服务器上的所有应用程序使用同一个类加载器。在这种配置下,每个应用程序不再有自己的类加载器。
Multiple:应用服务器上的每个应用程序使用自己的类加载器。
2.应用程序配置:Web模块类加载器策略
应用程序中对Web模块类加载器有两种配置:
Application:整个应用程序内的所有的实用程序jar包和Web模块使用同一个类加载器。
Module:应用程序内的每个Web模块使用自己的类加载器。应用程序的类加载器仍然存在,负责加载应用程序中Web模块以外的其它类,包括所有的实用程序jar包。
从上面的定义可以看出,不同的类加载器策略的配置下,类加载器的层次结构上的某些类加载器可能不存在。比如在应用程序服务器的应用程序类加载器策略定义为single的情况下,应用程序的类加载器将不存在,同一个应用服务器上的所有应用程序将共用同一个类加载器,这也就意味着不同的应用程序之间的类是共享的,应用程序间不能存在同名的类。
4 Jboss启动及加载过程
详细参考:http://tech.it168.com/j/2007-06-27/200706271521984.shtml
1) org.jboss.Main.main(String[]) 为入口.
2) main 函数创建一个名叫”jboss”的线程组, 然后创建一个属于该组的线程, 在线程中执行boot方法.
3) boot 方法首先处理main函数中的参数(及一些其它的系统环境设置), 接着就用系统的属性创建了org.jboss.system.server.ServerLoader实例[new ServerLoader(props)].
4) ServerLoader 注册Jboss相关的类路径, 包括XML解析器, jboss-jmx.jar, concurrent.jar及其它的一些额外的类路径.
5) ServerLoader 通过load(ClassLoader)方法创建Jboss Server实例. 参数ClassLoader是ClassLoader parentCL = Thread.currentThread(). getContextClassLoader( )得到的当前线程的类加载器. 创建的Server实例是org.jboss.system.server.Server接口的实现. load(ClassLoader)方法的细节:
Ø 用jar包及在ServerLoader中注册的类路径创建一个URLClassLoader的实例, 把传入的ClassLoader作为该URLClassLoader的parent.
Ø Server 接口的实现类由系统属性 jboss.server.type决定, 默认是 org.jboss.system.server.ServerImpl.
Ø URLClassLoader 通过无参构造函数加载Server接口实现的实例. 在加载前把当前线程的类加载器置为该URLClassLoader, 在加载完成后再置回之前传入的ClassLoader.
6) Server 实例用系统属性进行初始化[server.init(props)].
7) 服务起动[server.start()]. 起动过程的默认实现如下:
Ø 把当前线程类型加载器置为加载该Server接口实现实例的ClassLoader.
Ø 在jboss域内, 通过MBeanServerFactory的createMBeanServer(String)方法创建MbeanServer实例.
Ø 在MBean Server上注册ServerImpl和ServerConfigImpl两个MBean.
Ø 初始化统一的类加载仓库(unified class loader repository), 用来装载服务器配置目录及其它可选目录下的jar文件. 对于每一个jar文件和类目录都会创建一个相应的org.jboss.jmx.loading.UnifiedClassLoader实例, 并且注册到统一的仓库中. 其中一个UnifiedClassLoader实例会被设置为当前线程上下文的ClassLoader. [?: This effectively makes allUnifiedClassLoaders available through the thread context class loader.]
Ø 接下来创建org.jboss.system.ServiceController的MBean实例. ServiceController管理JBoss MBean服务的生命周期.
发表评论
-
java读取远程url图片,得到宽高
2010-03-19 11:43 2194import java.io.IOException; imp ... -
JAVA閏年判斷
2008-11-29 09:25 3773方法1: int year = 2008; boole ... -
java读取word的几种方式
2008-11-21 21:52 145811.使用apache poi组件 先到http://p ... -
Java的16进制与字符串的相互转换函数
2008-11-21 21:46 2585/** * 将指定byte数组 ... -
JAVA移动指定文件夹内的全部文件
2008-11-21 21:45 1972public static void fileMove(Str ... -
Java反编译工具Eclipse插件--Jode Decompiler
2008-11-21 13:10 3370安装非常的简单: help => Software U ... -
JDK不兼容异常(class file has wrong version 49.0...)
2008-11-18 09:11 8125昨天在調試程序時出現 ... -
getOutputStream() has already been called for this
2008-11-18 09:05 15931. tomcat5下jsp出现getOutputStrea ... -
用BAT运行java Application
2008-06-03 19:38 4074新建一个目录,作为打包的目录,比如ring目录,在这个目录里建 ... -
Java如何调用可执行文件和批处理命令
2007-07-27 17:25 1842java 代码 我们 ... -
JSTL的几个高级用法(转贴)
2007-07-03 14:15 2076fn函数 JSTL1.1标签库还 ... -
JSP验证码出现异常的解决方法
2007-07-03 14:14 1380在做图形验证码的时候随便从网上找了段代码,结果出现了这个异常, ...
相关推荐
冲突的根本原因在于WAS的类加载机制。默认情况下,WAS会优先使用其自身的类库,而非应用中提供的类库,即使应用中的类库版本可能更匹配。为了解决这个问题,我们可以采取以下步骤: 1. **删除冲突的JAR包**:首先,...
在整个过程中,理解WebSphere Application Server的部署机制和Spring Boot的运行原理至关重要。WAS提供了高级的管理、监控和集群功能,适合大型企业的生产环境。而Spring Boot的简洁性和自动化特性则使得开发和调试...
- **Struts2错误处理与自动加载web.xml**:WebSphere下部署Struts2应用时,可能遇到错误处理机制失效或web.xml修改后未生效的问题。确保应用重启策略正确,以及JSP预编译等设置符合需求。 以上是基于给定文件的...
- **轻量级**:Tomcat相比其他全功能的Web服务器(如Apache HTTP Server或IBM WebSphere)占用更少的资源,启动和运行速度快。 - **Servlet支持**:Tomcat完全遵循Servlet规范,提供Servlet的执行环境。 - **JSP...
2. **获取配置文件路径问题**:WebSphere与Tomcat环境下的资源加载机制不同。如果在`getClassLoader().getResource("").getPath()`中获取配置文件失败,可尝试将配置文件移动到`${WAS_INSTALL_ROOT}/profiles/AppSrv...
在使用 WebSphere eXtreme Scale 开发应用程序时,必须注意类加载器和类路径设置。类加载器负责加载应用程序所需的类和库,而类路径定义了类加载器搜索类的位置。为了确保应用程序能够正确运行,开发者需要配置正确...
5. **热部署**:在开发过程中,TomCat支持类加载器的热更新,当检测到应用目录下的文件变化时,可以自动重新加载修改,无需重启服务器。 **TomCat与其他服务器的集成:** 1. **与Nginx集成**:通过反向代理,Nginx...
- JVM调优:合理设置JVM堆大小(-Xms, -Xmx),开启垃圾回收策略,优化类加载机制。 - 部署优化:将静态资源分离,减少对Servlet的请求,启用GZIP压缩等。 5. **安全与防火墙配置** - 防止目录浏览:在web.xml中...
- **Servlet生命周期**: Servlet是Java编写的Web组件,Tomcat负责加载、初始化、服务和销毁Servlet实例。 - **请求处理**: 当客户端发送HTTP请求到Tomcat时,它通过Connector接收请求,然后由Engine(引擎)分发到...
而对进阶用户来说,理解Tomcat的架构,例如工作线程模型、类加载机制以及会话管理,有助于他们更好地优化和调试应用。 在实际使用中,Apache Tomcat 6.0.32常与开发工具(如Eclipse、IntelliJ IDEA等)集成,或者...
1. **轻量级**:Tomcat7是一个轻量级服务器,相比于其他重量级的应用服务器,如IBM WebSphere或Oracle WebLogic,它的体积小,启动快速,资源消耗低,这使得它成为开发和测试环境的理想选择。 2. **Servlet容器**:...
作为一个轻量级应用服务器,Tomcat相较于其他更重量级的Java EE应用服务器(如IBM WebSphere或Oracle WebLogic)来说,启动更快,资源占用更少,因此在小型和中型应用中非常流行。 在Tomcat 8.5中,有以下几个关键...
集成过程类似于其他Web服务器(如Weblogic与Apache或Tomcat与Apache的集成),主要依赖于插件机制。IBM提供了一个称为`plugin-cfg.xml`的配置文件,该文件定义了如何将HTTP请求路由到正确的WebSphere实例。通过在IHS...
- **更好的安全特性**:此版本增强了安全性,包括加强的身份验证和授权机制,以及对SSL/TLS的支持,确保了数据传输的安全性。 - **管理工具**:提供了用于管理应用程序、虚拟主机和服务器的管理工具,方便了开发者...
虽然功能相比其他商业应用服务器(如IBM WebSphere或Oracle WebLogic)可能较为有限,但对初学者和小型项目来说,Tomcat已经足够满足需求。 Servlet是Java编程语言中用来扩展服务器功能的接口。它允许程序员创建能...
7. **热部署**:在Tomcat运行时,开发者可以修改Web应用的类或资源,无需重启服务器,Tomcat会自动检测变化并重新加载。 8. **可扩展性**:虽然Tomcat本身是轻量级的,但可以通过与其他Java EE组件(如EJB容器)...
`load`方法返回的是一个代理对象,只有在真正访问实体属性时才会触发数据库查询,这是一种延迟加载机制。如果实体不存在,`load`将抛出`ObjectNotFoundException`。 #### Java基本数据类型 Java提供了八种基本数据...
10. **JVM原理**:虽然不是考试的常规内容,但了解JVM(Java Virtual Machine)的工作原理,如内存模型、垃圾回收和类加载机制,可以帮助你更好地理解和优化Java程序。 这个压缩包中的"说明.htm"可能是考试大纲或者...
Class.forName用于动态加载类,便于实现灵活的类加载机制;GET与POST请求的区别在于数据传输方式和可见性;JSP中的动态INCLUDE与静态INCLUDE主要在于编译时机和页面共享变量。 【就业与面试技巧】 在求职过程中,...