java类加载机制概述2

一 web容器类加载机制

1 tomcat类加载机制

Tomcat中的类加载策略和JDK中的委托模型略有不同。Tomcat Server在启动的时候将构造一个ClassLoader树,以保证模块的类库是私有的,ClassLoader结构如下:

 

               Bootstrap
                   |
              System
                  |
            Common
          /                \
 Catalina          Shared
                      /  ... ...    \
            webapp1        
webappN
1)Bootstrap ClassLoader: 
负责加载由虚拟机提供的基本运行时类和系统扩展目录($JAVA_HOME/jre/lib/ext)下的JAR包
2)System ClassLoader: 
通常这个加载器用来加载CLASSPATH环境变量中指定的类,但在Tomcat5的标准启动脚本($CATALINA_HOME/bin/catalina.sh或%CATALINA_HOME%/bin/catalina.bat)中改变了它的行为,它只加载下面的类:
$CATALINA_HOME/bin/bootstrap.jar    // 包含 main() 方法来初始化Tomcat 5 server, 包含类加载器实现类. 
$JAVA_HOME/lib/tools.jar // Contains the "javac" compiler used to convert JSP pages into servlet classes. 
$CATALINA_HOME/bin/commons-logging-api.jar // Jakarta commons logging API. 
$CATALINA_HOME/bin/commons-daemon.jar // Jakarta commons daemon API. jmx.jar // The JMX 1.2 implementation.
    3)Common ClassLoader

它负责加载Tomcat本身和所有的web应用都能看到的类。通常,应用的类不应该由他加载

 

$CATALINA_HOME/common/classes,$CATALINA_HOME/commons/endorsed和$CATALINA_HOME/common/lib下的类都由这个加载器加载。缺省的,包括: 
ant.jar - Apache Ant. 
commons-collection.jar  // Jakarta commons collection. 
commons-dbcp.jar // Jakarta commons DBCP, providing a JDBC connection pool to web applications. 
commons-el.jar // Jakarta commons el, implementing the expression language used by Jasper. 
commons-pool.jar // Jakarta commons pool. 
jasper-compiler.jar // The JSP 2.0 compiler. 
jasper-runtime.jar // The JSP 2.0 runtime. 
jsp-api.jar // The JSP 2.0 API. 
naming-common.jar // The JNDI implementation used by Tomcat 5 to represent in-memory naming contexts. 
naming-factory.jar // The JNDI implementation used by Tomcat 5 to resolve references to enterprise resources (EJB, connection pools). 
naming-resources.jar // The specialized JNDI naming context implementation used to represent the static resources of a web application. 
servlet-api.jar // The Servlet and JSP API classes. 
xerces.jar // The XML parser that is visible by default to Tomcat internal classes and to web applications.
xml-apis.jar

    4)Catalina ClassLoader

用来加载实现Tomcat自己需要的类。由它加载的类对web应用都是不可见的。$CATALINA_HOME/server/classes,$CATALINA_HOME/server/lib,都由这个加载器加载

    5)Shared ClassLoader

被所有的web应用共享的类和资源由这个加载器加载。$CATALINA_BASE/shared/classed,$CATALINA_BASE/shared/lib,都由这个加载器加载

    6)WebappXClassLoader

对每个Tomcat里的web应用都创建一个加载器,web应用下的WEB-INF/classes,WEB-INF/lib,都由这个加载器加载,由它所加载的类对其他的web应用是不可见的

 

WebSphere Application Server中的类加载机制

如下是WAS classloader层次
               JVM classloader
                   |
Websphere Extension classloader
                  |
Websphere lib/app classloader
                        |
 Websphere server classloader
                      /  ... ...    \
application classloader1       application classloaderN
1) JVM Classloader
这个层其实就是前面介绍的Java基本的classloader框架,由 bootstrap classloaderextension classloadersystem classloader三个classloader组成,主要是完成jre/lib下,java.ext.dir下,还有JVM classpath下面类的加载。

2)WebSphere Extensions Classloader

这个层的classloader主要完成WAS运行时所需要的类以及相关资源,比如JDBCResource Adapter,以及用户扩展WAS运行时库的目录,这一层的委托策略都是父亲优先(PARENT_FIRST)

3)WebSphere lib/app Class loader

这个层的classloader主要是为了兼容WAS Version 4的。它主要用来加载一些所有应用都共享的类,在Version 4以后,推荐用 Shared libraries来放需要共享的类库
4)WebSphere "server" Class loader
这层的classloader主要是来加载整个运行上当前服务器上的应用程序所共享的的类库,你可以通过定义特定的Shared libraries以来使当前的服务器中的应用程序共享它,,这一层的委托策略是父亲优先(PARENT_FIRST)

5) Application Class loader

 Application Module Class loader主要负责加载应用程序单元
Web Module Class loader应用程序中的Web单元,这时它的父亲就是Application Module Class loader
对于这两个classloader,可以采取的委托策略可以既是父亲优先(PARENT_FIRST),也可以父亲最后(PARENT_LAST)
建议:

1)不要把应用程序依赖的资源放在JVM的系统lib下让JVMclassloader去加载,原因是如果应用程序的委托策略设成PARENT_LAST,可能会造ClassNotFoundException

2)不要修改ws.ext.dirs这个系统属性以此来增加WebSphere Extensions Classloader的加载能力,原因是被扩展的目录可能跟当前已经目录中有冲突,会导致一此不可预期的问题

3)如查开启了动态重加载,这种情况下应用如果有对本地类库的依赖关系,最好使用WebSphere "server" Class loader来加载,这样服务器的整个生命周期这些库都能被应用程序可见,即使应用程序被重新加载

 

二 OSGI类加载机制

1.OSGi中的每个模块(bundle)都包含 Java 包和类。模块可以声明它所依赖的需要导入(import)的其它模块的 Java 包和类(通过 Import-Package),也可以声明导出(export)自己的包和类,供其它模块使用(通过 Export-Package
2.OSGi中的每个模块都有对应的一个类加载器。它负责加载模块自己包含的 Java 包和类。当它需要加载 Java 核心库的类时(以 java 开头的包和类),它会代理给父类加载器(通常是启动类加载器)来完成。当它需要加载所导入的 Java 类时,它会代理给导出此 Java 类的模块来完成加载。模块也可以显式的声明某些 Java 包和类,必须由父类加载器来加载。只需要设置系统属性 org.osgi.framework.bootdelegation的值即可。

 

3.JavaJ2EE的类加载模型都是层次化的,只能委托给上一层类加载器,OSGi类加载模型则是网络图状的,可以在bundle间互相委托(摘自http://kangzye.blog.163.com/blog/static/3681922320105130314194/
 
4. OSGI加载步骤
 

 5.eclipse插件加载
      Eclipse 使用 OSGi 作为插件系统的基础,早期版本的 Eclipse 也设计为插件集合,而且 Eclipse包括自己专用的插件系统来管理交互。但是,随着 Eclipse IDE 要求的增长,必须需要一个更强壮的解决方案。这个新系统的基本要求包括动态添加新插件和停止现有插件的能力。经过大量研究之后,Eclipse 创建者决定通过实现 OSGi 框架规范替换专用的插件框架。eclipse框架如图:


 
 

 

创建基于 Eclipse 的应用程序所需的最小插件集称为 Eclipse Rich Client Platform(RCP)。但是,插件本身不能启动。它们需要在一个环境中启动和操作。Eclipse 使用 OSGi R4 规范的实现提供了该环境。


 
       Platform Runtime 平台运行库是内核,它在启动时检查已安装了哪些插件,并创建关于它们的注册表信息。即在eclipse运行时发现和管理插件。为降低启动时间和资源使用,它在实际需要任何插件时才加载该插件。除了内核外,其他每样东西都是作为插件来实现的。
   eclipse插件关系如图:

----------------------            -------------------- 
|plugin A            |            |plugin B          | 
|   ---------------  | 
contibute  |  --------------  | 
|   | 
ext point p | <--------------- | extension  |  | 
|   ---------------  |_           |  --------------  | 
|         ||         | |          |        ||        | 
|   ---------------  | |implement |  --------------  | 
|   | interface I | <--|------------ | class  C   |  | 
|   ---------------  | |          |  --------------  | 
---------------------- |          ----------/ ------- 
                       |  create, call       | 
                       ----------------------|

 

三 SPI类加载机制

      JDBC API 介面類別(屬於核心類別函式庫)都是由Bootstrap Loader 或是ExtClassLoader 來載入, 可是JDBC driver 常常是藉由ExtClassLoader 或AppClassLoader 來載入,在Java 領域中只要分成API(Interface,公開制定,成为核心函数库)和SPI(特定厂商不同实现)都会有这个问题,解决办法是穿透双亲委托机制。使用线程上下文类加载器。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值