• 关于App class loader的总结


    关于App class loader的总结 2010-05-11 15:19:09

    分类: 系统运维

    Java本身是一种设计的非常简单,非常精巧的语言,所以Java背后的原理也很简单,归结起来就是两点: 

    1、JVM的内存管理 

    理解了这一点,所有和对象相关的问题统统都能解决 

    2、JVM Class Loader 

    理解了这一点,所有和Java相关的配置问题,包括各种App Server的配置,应用的发布问题统统都能解决 


    App Class Loader 
    |----- EJB Class Loader 
    |----- Web App Class Loader 


    如果在App Class Loader级别配置,是全局可见的。如果打包在EJB里面,那么就不会影响到Web Application,反之亦然,如果你在WEB-INF下面放置Hibernate,也不会影响到EJB。放在EJB Class Loader或者放在Web App Class Loader级别主要就是在局部范围内有效,不影响到其它的应用。 

    试想,如果在一个Weblogic上面配置多个虚拟域,你使用www.bruce.com域名,开发你的网站,我使用www.fankai.com开发我的网站,那么当然不希望我们的Hibernate相互干扰,所以就可以放在 EJB Class Loader级别来配置Hibernate。 

    进一步阐述一下EJB Class Loader的问题: 

    先再次强调一下,Hibernate和EJB,和App Server不存在兼容性问题,他们本来就是不相关的东西,就好像JDBC,相信没有人会认为JDBC和EJB不兼容吧,Hibernate也是一样,它只和JDBC驱动,和数据库有兼容性问题,而和EJB,和App Server完全是不搭界的两回事。凡是认为Hibernate和EJB不兼容的人,其实是都是因为对EJB学习的不到家,把责任推到Hibernate身上了。 

    我前面的帖子提到过Class Loader的层次,这里不重复了,总之我们先来看看Class Loader的作用范围: 

    BootStrap Class Loader: 

    load JRElib t.jar, sunrsasign.jar, charsets.jar, jce.jar, jsse.jar, plugin.jar 

    Ext Class Loader: 

    load JRElibext目录下的库文件, load JREclasses目录下的类 

    App Class Loader: 

    load CLASSPATH变量指定路径下的类 

    以上的load路径都是写死在JVM的C++源代码里面的,不能改变,详细请见王森的《Java深度历险》 

    在一个特定的App Server上,Class Loader会继续向下继承,继承的层次会根据不同的App Server有所不同,但是肯定不会变的就是: 

    EJB Class Loader: 

    继承自App Class Loader,继承层次根据App Server有所不同,一个EJB Class Loader它的load Class的范围仅限于JAR或者EAR范围之内。 

    Web App Class Loader: 

    继承自App Class Loader,继承层次根据App Server有所不同,一个Web App Class Loader:它的load Class的范围在 WEB-INFlib下的库文件和WEB-INFclasses目录下的class文件。 

    Web App Class Loader很好理解,大家毕竟用的很多,App Server上的一个Web Application会创建一个Web App Class Loader的实例去负责load class,所以如果你想让Hibernate只在这个Web Application内生效,把它放到WEB-INFlib下去就好了。 

    如果你把Hibernate放到了CLASSPATH变量指定的路径下,而你在WEB-INFlib也放了一份,那么Web App Class Loader由于load范围所限,它会首先找到WEB-INFlib下的那份Hibernate,按照它的配置来初始化Hibernate。 

    如果你把Hibernate放到了CLASSPATH变量指定的路径下,但你在WEB-INFlib什么都没有放,那么Web App Class Loader由于load范围所限,它根本什么都找不到,于是它把load Hibernate的责任交给上一级的Class Loader,这样直到App Class Loader,它找到了Hibernate,按照它的配置来初始化Hibernate。 

    EJB Class Loader稍微复杂一点,不那么容易理解。App Server会针对每一个EJB包文件创建一个EJB Class Loader的实例,例如: 

    HelloRobbin.jar 
    HelloBruce.jar 

    当你把这两个jar发布到App Server上以后,会创建两个EJB Class Loader的实例,分别去load这两个EJB包,比如说: 

    CLEJB_Robbin是load HelloRobbin.jar的 
    CLEJB_Bruce是load HelloBruce.jar的 

    那么CLEJB_Robbin的load范围就仅仅限于HelloRobbin.jar之内,它load不到HelloRobbin.jar之外的任何文件,当然它也load不到HelloBruce.jar。 

    说到这里,我相信大家应该已经明白为什么EJB规范不允许EJB有IO操作了吧?因为EJB Class Loader根本找不到jar包之外的文件!!! 

    如果现在你想实现HelloRobbin.jar和HelloBruce.jar的互相调用,那么该怎么办?他们使用了不同的EJB Class Loader,相互之间是找不到对方的。解决办法就是使用EAR。 

    现在假设HelloRobbin.jar和HelloBruce.jar都使用了Hibernate,看看该怎么打包和发布: 

    HelloEJB.ear 
    |------ HelloRobbin.jar 
    |------ HelloBruce.jar 
    |------ Hibernate2.jar 
    |------ pojo.jar (定义所有的持久对象和hbm文件的jar包) 
    |------ cglib-asm.jar 
    |------ commons-beanutils.jar 
    |------ commons-collections.jar 
    |------ commons-lang.jar 
    |------ commons-logging.jar 
    |------ dom4j.jar 
    |------ odmg.jar 
    |------ log4j.jar 
    |------ jcs.jar 
    |------ hibernate.properties 
    |------ log4j.properties 
    |------ cache.ccf 
    |------ META-INFapplication.xml (J2EE规范的要求,定义EAR包里面包括了哪几个EJB) 

    除此之外,按照EJB规范要求,HelloRobbin.jar和HelloBruce.jar还必须指出调用jar包之外的类库的名称,这需要在jar包的manifest文件中定义: 

    HelloRobbin.jar 
    |------ META-INFMANIFEST.MF 

    MANIFEST.MF中必须包括如下一行: 

    Class-Path: log4j.jar hibernate2.jar cglib-asm.jar commons-beanutils.jar commons-collections.jar commons-lang.jar 
    commons-logging.jar dom4j.jar jcs.jar odmg.jar jcs.jar pojo.jar 

    这样就OK了,当把HelloEJB.ear发布到App Server上以后,App Server创建一个EJB Class Loader实例load EAR包里面的EJB,再根据EJB的jar包里面的MANIFEST.MF指出的Class-Path去寻找相应的jar包之外的类库。 

    所以一个EAR包有点类似一个Web Application,EJB Class Loader的load范围也就是EAR范围之内,它load不到EAR之外的文件。除非把Hibernate定义到CLASSPATH指定的路径下,在这种情况下,EJB Class Loader找不到Hibernate,只能交给上一级的Class Loader,最后由App Class Loader找到Hibernate,进行初始化。 

    没有写完,继续说... 

    由于EAR这样load Class规则,假设Robbin和Bruce都在同一个Weblogic上运行自己的网站,而我们都不希望自己的程序里面的Hibernate配置被对方的搞乱掉,那么我们就可以这样来做: 

    Robbin's Website: 

    Robbin.ear 
    |-------- robbin.war (把Web Application打包) 
    |-------- robbin.jar (把开发的EJB打包) 
    |-------- Hibernate2.jar 
    .......................... 
    |-------- META-INFapplication.xml 


    Bruce's Website: 

    Bruce.ear 
    |-------- bruce.war (把Web Application打包) 
    |-------- bruce.jar (把开发的EJB打包) 
    |-------- Hibernate2.jar 
    .......................... 
    |-------- META-INFapplication.xml 

    这样在同一个App Server上运行,就可以互相不干扰。
  • 相关阅读:
    [工作中的设计模式]中介模式模式Mediator
    [工作中的设计模式]责任链模式chain
    [工作中的设计模式]迭代子模式Iterator
    [工作中的设计模式]组合模式compnent
    TI IPNC Web网页之流程分析
    TI IPNC Web网页之GoDB开发环境
    安装ubuntu时将boot目录单独挂载的意义
    ubuntu添加自定义vga输出分辨率
    GCC编译默认的头文件搜索路径
    设置搜狗输入法在任何时候按左右两侧的shift激活
  • 原文地址:https://www.cnblogs.com/developer-ios/p/5820619.html
Copyright © 2020-2023  润新知