Java_关于App class loader的总结
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 JRE\lib\rt.jar, sunrsasign.jar, charsets.jar, jce.jar, jsse.jar, plugin.jar
Ext Class Loader:
load JRE\lib\ext目录下的库文件, load JRE\classes目录下的类
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-INF\lib下的库文件和WEB-INF\classes目录下的class文件。
Web App Class Loader很好理解,大家毕竟用的很多,App Server上的一个Web Application会创建一个Web App Class Loader的实例去负责load class,所以如果你想让Hibernate只在这个Web Application内生效,把它放到WEB-INF\lib下去就好了。
如果你把Hibernate放到了CLASSPATH变量指定的路径下,而你在WEB-INF\lib也放了一份,那么Web App Class Loader由于load范围所限,它会首先找到WEB-INF\lib下的那份Hibernate,按照它的配置来初始化Hibernate。
如果你把Hibernate放到了CLASSPATH变量指定的路径下,但你在WEB-INF\lib什么都没有放,那么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-INF\application.xml (J2EE规范的要求,定义EAR包里面包括了哪几个EJB)
除此之外,按照EJB规范要求,HelloRobbin.jar和HelloBruce.jar还必须指出调用jar包之外的类库的名称,这需要在jar包的manifest文件中定义:
HelloRobbin.jar
|------ META-INF\MANIFEST.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-INF\application.xml
Bruce's Website:
Bruce.ear
|-------- bruce.war (把Web Application打包)
|-------- bruce.jar (把开发的EJB打包)
|-------- Hibernate2.jar
..........................
|-------- META-INF\application.xml
这样在同一个App Server上运行,就可以互相不干扰。
Java_关于App class loader的总结的更多相关文章
- App Class Loader
Java本身是一种设计的非常简单,非常精巧的语言,所以Java背后的原理也很简单,归结起来就是两点: 1.JVM的内存管理 理解了这一点,所有和对象相关的问题统统都能解决 2.JVM Class Lo ...
- 关于App class loader的总结
关于App class loader的总结 2010-05-11 15:19:09 分类: 系统运维 Java本身是一种设计的非常简单,非常精巧的语言,所以Java背后的原理也很简单,归结起来就是两点 ...
- nova-api源码分析(APP的创建)
目录结构如下: 上面介绍了nova-api发布所用到的一些lib库,有了上面的基础知识,再来分析nova-api的发布流程,就比较轻松了.nova-api可以提供多种api服务:ec2, osapi_ ...
- webpack入门(四)——webpack loader 和plugin
什么是loader loaders是你用在app源码上的转换元件.他们是用node.js运行的,把源文件作为参数,返回新的资源的函数. 例如,你可以用loaders告诉webpack加载 coffee ...
- node作为前台的项目如何打包静态js和css并生成版本号,loader插件的使用
一.使用场景: 1.node创建的前台项目需要输入地址展示页面 2.有设置缓存或者cdn的需要在静态文件更改时能使用新的而不是缓存的,需要版本号这里 3.可能需要压缩静态文件的 二.一些参考地址,需要 ...
- App支付宝支付--PHP处理代码
/* *生成APP支付订单信息 * @param number uid 用户id * @param string token 用户token * @param number oid 订单id * @p ...
- java内省机制及PropertyUtils使用方法
背景 一般情况下,在Java中你可以通过get方法轻松获取beans中的属性值.但是,当你事先不知道beans的类型或者将要访问或修改的属性名时,该怎么办?Java语言中提供了一些像java.bean ...
- 在 node.js 的 express web 框架中自动注册路由
该方法主要是动态注册自己写的 router . 注册器 router 文件名为 loader.js . var express = require('express'); var fs = requ ...
- 如何用bat批处理编译swf项目
平时用FB等IDE编译多模块的游戏项目时,除了添加移除模块的操作很繁琐外,编译速度也非常之慢.而用bat来编译swf项目,速度非常快,稳定. 在此分享自己工作用的bat,每次运行会重新编译主模块Gam ...
随机推荐
- Swipe JS – 移动WEB页面内容触摸滑动类库
想必做移动前端的同学经常会接到这样子的一个需求,就是在移动设备页面上的banner图能够用手指触摸左右或上下的滑动切换,这在移动设备是个很常见的一个效果,其用户体验远甚于点击一个按钮区域,通过手指的触 ...
- 运维自动化之ansible的安装与使用(包括模块与playbook使用)(转发)
原文 http://dl528888.blog.51cto.com/2382721/1435415 我使用过puppet(地址是http://dl528888.blog.51cto.com/2382 ...
- android 入门-android Studio 快捷输入
1.输入 log的时候按一下Tab.就会打出 private static final String TAG="Settings"; 2. shift +alt+x 运行 shif ...
- Ubuntu14.04LTS系统QQ的安装:pidgin-lwqq
本人是轻度聊天工具使用者(大言不惭是轻度,偷笑),发现输入法到博主也有解决linux下QQ的解决方法,一并抄过来,有需要,请联系原作者 参考链接:http://www.cnblogs.com/zhj5 ...
- 如何更快的删除String中的空格[未完]
背景:此文章主要源于网址[1]所描述的,文中大部分方法亦是[1]中实现的. 下面介绍集中删除空格的方法: 方法1:按空格分割后再拼接 /// <summary> /// 按空格分割后拼 ...
- ubuntu中禁用华硕S550C触摸屏的方法
华硕S550C的触摸屏被我一不小心弄了一条裂缝,导致屏幕一直会莫名其妙自动进行点击,严重影响了使用.在windows 系统下通过FN+F7的快捷键可以直接禁用触摸屏,但是换成ubuntu 系统之后,快 ...
- 运行在linux上的mysql常用命令
mysql的注释:--或者# 1.mysql服务进程的命令 service mysqld start;#启动mysql服务 service mysqld status;#查看服务状态 service ...
- AndroidStudio里面怎么取消与SVN的关联
在公司做项目 遇到SVN解除关联的问题 后经过解决: 1.解除文件的关联方法: 1.1. 创建一个reg文件 如下 1.2 在文件中填入如下内容并保存: Windows Registry Editor ...
- Vs2012调试本地windows服务
背景: 在我的工作经历中,我用到了一个我们以前学习中没有接触过的老东西-服务.之所说以前没有接触过,是因为自己没有系统的研究过这东西:之所以又说它是老东西,是因为我们其实早就知道他的存在,经常用它去干 ...
- 【maven】 pom.xml详解
pom.xml详解 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www ...