<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>zwchen</title>
    <description>热爱大自然，喜欢探索一些本质性的东西。
Email/msn/gtalk统一地址：chenzhiwu#gmail.com

</description>
    <link>http://zwchen.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>RSS阅读器选择心得</title>
        <author>zwchen</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zwchen.javaeye.com">zwchen</a>&nbsp;
          链接：<a href="http://zwchen.javaeye.com/blog/150199" style="color:red;">http://zwchen.javaeye.com/blog/150199</a>&nbsp;
          发表时间: 2007年12月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          这几天，试用了好几个RSS阅读器，花了不少时间。也许很多人很吃惊：你现在才玩这个，火星上来的吧？<br /><br />虽然我每天都会google大量的资料，但我觉得自己的信息源还是比较单一，因为搜索往往有一个主题，譬如我这三个月一直关于RIA、UI框架的设计，Java界有什么新闻，关注并不多，所以我现在需要一个聚合的东西，当然就是RSS阅读器了。这东西就不用重复了，三年前提它也许还有点新鲜感。一句话总结：当你有5个每天必访的网站时，RSS阅读器的优势就体现出了，就如同SSO技术对于门户集成。<br /><br />我几天前还吃惊，为什么一位同事能够在第一时间知道dojo发布了1.0版，Adobe Flex计划将Livecyle Data Service、AMF实现开源？这对我当前的工作影响多大啊。原来是他有RSS阅读器。<br /><br />我特别希望这个RSS阅读器有如下功能，于是我总结了一下几个核心需求，当然也许并不适合大家。<br />1、我能够从Google Reader上将我的rss订阅导出，也就是要求RSS客户端必须完美支持opml导入。顺便说一点，这个功能可以pk掉几乎一半的RSS阅读器。下文会说明。<br /><br />2、RSS阅读器的摘要部分（也就是文章正文，RSS2.0对应是description，Atom1.0对应是summary和content），应该能够正常解析和格式化。而且description为空时，能够链接到原文。譬如很多IT新闻，我只要花半分钟看看摘要就够了。而且，因为摘要是保存到本地数据库，所以非常快。<br /><br />3、桌面提示（就是类似于msn的上线通知）。够强制性推给我一些东西，就像Foxmail定时收取公司信件一样。我经常一下班就回家了，在家也不开电脑，所以最好利用上班时间的缝隙。我希望它在设计上人性化：提示效果平滑，提示内容是标题列表，提示时间可控。<br /><br />4、能够阅读文章的评论。<br />5、能够prefetch（文章预取），以便快速阅读。<br />6、界面美观，导航清晰，操作简单。<br /><br />以上前三个是核心的，我要求的阅读器必须能够满足。<br /><br /><br />以前用<strong>Google Reader</strong>大概几个月，但还是觉得不太方便，如：<br />1、它仿OutLook的收缩Tab：点击文章列表自动展开当前的摘要。我用了一段时间后觉得还是不喜欢，文章长了咋办？还是习惯Foxmail那种阅读模式：左边导航树，右上是文章列表、右下是文章详细内容。以前就是因为MSN的space只能在Blog的首页显示全文，那些长篇大论的blog我就没法读了，所以用了几个月后就放弃了。JavaEye的摘要+列表方式显示，我最满意，呵呵。<br />2、它没有翻页功能，是实时动态加载文章列表。但要看该作者的历史文章都要拖动那个上下滚动条好半天。<br />3、不得不提的是，Google reader的历史文章不知道是从哪儿取得的，因为我研究RSS、Atom规范，并没有加载历史文章的接口，譬如该Blog作者05年的文章。而且各离线阅读器的初始文章列表都是默认加载最新的RSS，也就是你直接浏览RSS的那个xml文件的几篇文章。这应该是Google Reader 亮点。谁知道它是怎么实现的，告诉一声哦。<br />4、它并没有充分利用浏览器的空间，譬如浏览器本身的菜单、工具条、地址栏、状态栏不说，它内部也有很多空间被浪费了。譬如我就不喜欢Google Reader左上6、7行链接。因为我本来想利用这个空间来展示更多的blog导航树。<br />5、因为是在线阅读，每次打开都比较慢。另外还要我主动打开，我可没有这么积极，至少在我没有养成习惯前。<br /><br />当然了，Google Reader有个特别的优势，就是国外很多blog订阅是用<a href="Feedburn.com" target="_blank">Feedburn.com</a>做的聚合，譬如我最喜欢的站点之一www.theserverside.com的RSS，而它和wikipedia、blogspot有同样的命运，被GWF了，而用Google Reader这种服务器端获取方式，就可以绕开。<br />我就说说我选择RSS阅读器的过程吧。<br /><br /><strong>桌面提示功能重要性由来</strong>。起先，我是想到email订阅方式的。我试用了几个，譬如国内的“<strong>RSS邮天下</strong>（http://www.emailrss.cn）”，国外的<strong>SendMeRSS</strong>（http://www.sendmerss.com）。问题是：<br />OPML里有几个是RSS地址，咋导入？另外，即使一个个添加，也需要提交、确认等过程，非常麻烦。<br />还有，就是发送的文章只是一个摘要，还要人去网站取，譬如我喜欢的infoQ.com网站，RSS的Description部分就只有几行，而它的文章质量是非常高的，很值得看全文。从FoxMail再转到IE或Firefox，挺费劲的（邮件的里的链接默认是IE打开，而我的偏好是用Firefox）。<br />另外，RSS推送的实时性也很不友好，我也不希望批量发送。<br />还要说一点，是这种公共邮件往往会被公司的邮件网关当成的垃圾。<br /><br />  于是，我寻找RSS桌面客户端软件。<br />几年前，我用FeedDemon的1.x版本，大概是破解的（破解就意味着为了新功能升级时，你又得花时间去寻找下一个破解版）。后来感觉它和IE浏览没啥优势，可能是看的文章不多。到现在已经两三年过去了。发现不用RSS订阅就太没与时俱进了:我需要的阅读更多的文章，特别是新闻类，它们主要是摘要性质的。<br /><br />我半年前试用过国内的若干款RSS阅读器，譬如周博通、新浪点点通等等，差不多都下载安装了一遍，可怜我机器后来的速度（Windows注册表中的垃圾）。因为OPML文件的导入不成功的，就排除了好几款（OPML是RSS阅读器移植的前提啊）。使用不习惯也排除了一些。总之国内的RSS阅读器就没有我满意的。<br />也记得当时选用网摘服务，注册了不下15家网站，那个著名的365key的搜索功能总是error，用了大半年后实在无法忍受，干脆放弃了。<br /><br />那时候最终选择了<strong>周博通</strong>，现在也记不得是啥原因也对它不满意。<br /><br />后来用<strong>Foxmail</strong>自带的RSS阅读器，我忍受了它对我的OPML文件无法导入，至少其它的阅读器还可以成功导入部分。但无法忍受它的文章内容的解析：乱码，格式混乱。<br /><br />其间记得也试用过用Java的SWT开发的<strong>RSSOwl</strong>，当时也是无法忍受其中文乱码问题，当然试用它是两年前的事情。<br /><br />最近接连试用了几款，应该都是非常受欢迎的，大家不妨看看这个RSS阅读器排行：<a href="http://email.about.com/od/rssfeedreaders/Find_the_Best_RSS_Feed_Readers_News_Aggregators.htm" target="_blank">http://email.about.com/od/rssfeedreaders/Find_the_Best_RSS_Feed_Readers_News_Aggregators.htm</a> 。<br /><br />说说我的选择过程吧：<br /><strong>Mozilla Thunderbird</strong>：这个应该是非常知名的，但对opml导入没法分级。默认界面也不是很漂亮（应该有类似Firefox的自定义皮肤）。默认的摘要解析也太朴素了，没有样式美化。算了，再找找吧。<br /><br /><strong>FeedReader</strong>：免费知名的RSS阅读器。界面简洁美观，导航清晰、操作方便。国际化支持良好，虽然对我没用，但其它几款不支持。opml导入支持太优秀了（相对于我以前用过的所有RSS阅读器）。但有个我无法忍受的地方，就是对文章description解析部分太差，80%的出错。要知道，很多文章我只愿意花半分钟。其它都非常满意。<br /><br /><strong>FeedDemon</strong>：这款应该是大家都认识的，太知名了，但国内大多数用户应该都是破解版的，虽然注册只需要几十美元，但试用时，谁知道那近200 RMB是否值得淘，而且付款过程也挺费劲的。它没有FeedReader的毛病，但我还是有几个细节我不太满意。界面图标太粗糙了。另外，它的桌面提示只是显示这样的信息：“Jack’s Blog has 2 new items”，而不是像FeedReader那样显示那些items的标题。那个提示框的醒目删除图片也很不爽。<br />FeedDemon还有个preFetch的功能，可以下载文章供断网阅读。<br /><br /><strong>Omea Reader</strong>：这个所谓排行第一的免费RSS Reader。开始安装后，对其界面很不满意，鼠标移到菜单上就闪烁。而且集成很多根本对我无用的功能，譬如news server、contacts、notes。我看了一下官方网站，它想做桌面阅读客户端门户，譬如集成浏览器、邮件阅读器、搜索、文档查看（不用再直接打开word了）、联系人、工作任务等等。当然，这些功能都是以插件方式提供，这点还是不错。我可以删除我不用的功能。我给它瘦身半小时，终于满意。<br />Omea Reader有个特别的地方，就是可以自动下载rss文章的评论。<br /><br /><strong>Awasu RSS Reader</strong>：这个也评价很高，但个人版只能导入100个rss地址，另外也没有发现特别的亮点，安装试用10分钟我就卸载了。<br /><br />最后我还是选择了Omea Reade，但找到更喜欢的，我可能还是会换掉。大家也帮忙推荐一下吧，最好是实际的试用体会。<br /><br />我觉得我以后会比较依赖RSS这种东西，所以值得投入点时间。搞软件开发几年了，对大众软件装装卸卸的确实不再感兴趣了。记得大学时代，大概6六年前，那时候不是很多卖大众软件光盘的吗？我经常一下子把上百个软件一个一个试用，那个热情啊，那时候的Windows 98，一个月装一次。<br /><br />对RSS客户端的一番调研，再次体会到Web2.0网站倡导的简洁、实用。每个RSS阅读器都可以挑出毛病，也许，那只是个人的偏好吧。另外，我觉得RSS阅读器的设计者，一定要有丰富的RSS订阅经历。也许，这就是所谓的业务背景、行业知识吧。
          <br/>
          <span style="color:red;">
            <a href="http://zwchen.javaeye.com/blog/150199#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 22 Dec 2007 22:23:54 +0800</pubDate>
        <link>http://zwchen.javaeye.com/blog/150199</link>
        <guid>http://zwchen.javaeye.com/blog/150199</guid>
      </item>
      <item>
        <title>辞职感言</title>
        <author>zwchen</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zwchen.javaeye.com">zwchen</a>&nbsp;
          链接：<a href="http://zwchen.javaeye.com/blog/123806" style="color:red;">http://zwchen.javaeye.com/blog/123806</a>&nbsp;
          发表时间: 2007年09月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          终于离开我工作近两年的公司了。<br />两个月多前就有辞职的念头。一个半月前，大连一家软件公司通过51job找到我，然后叫我去面试。面试很顺利，因为是做底层大型平台的研发，当时我担心领域太窄，很犹豫，后来公司部长多次和我沟通，我的疑虑才解除了。前后经过一个月，我才决定去他们那儿。其实，我本来是打算去上海发展，像上海的ebay、IBM研发部门。这家公司共有约300人的研发队伍，包括基础平台和业务平台。总之职位和待遇我都比较满意。当然了，进去后呆一个月才能知道期望和现实的差别。<br /><br />离开现在这家公司是必然的。在我进入公司后几个月，我就预测我很难在这家公司干满三年，现在的离职时间和我当时的预计一致。因为合同是三年，所以我并没有将档案和人事关系转过来，当然公司也没有给我交纳任何保险，他们说是档案转过来后再补上。因为从我进公司的时候，就想到我离开公司的一天，所以我工作非常努力，认真负责，几乎得到了所有同事和领导的高度认可。我在公司给人的印象是充满热情、积极主动、好学、乐于助人，有个性。但给认还有一个可悲的印象：一个偏执于技术的人，说得难听点，就是井底之蛙。因为我来公司的近一年时间内，主要是解决项目中的技术问题，做一些纯技术的模块，基本没有安排和业务相关的活给我干。<br /><br />先说说我们公司吧。公司很大，在国外和国内约有10个分公司，也快上市了，主要是做项目，没有自己的核心产品。别的部门和分公司可以说是外包，但我们部门不是，我们一般都是从需求调研开始做的大项目。大家知道，国内做项目的公司，关注点一般都不在技术，公司领导就认为技术人员可以一把一把抓。用Struts、Spring啥的对项目的影响几乎就是5%不到。说我搞技术吧，就是拿别人的产品或开源框架来用（时间紧啊）；搞业务吧，没我的份。回过头来想想，我给别人的印象也是我自己造成的，怨不得谁。但是我现在也非常关注业务，关注业务给客户带来的价值。一堆钢铁和砖块有用吗？如果它不是用来盖房子。<br /><br />当前的项目实际，往往是领导以接单子和完成合同为中心，员工以领导为中心，谁以客户为中心？但说实话，国企这类传统客户，还真不好沟通。项目验收时公司大领导换了，你就哭吧；客户负责人不懂技术，硬是拿产品的需求来要求你，你就认了吧。客户分阶段要概要设计文档、详细设计文档，去一次，忽悠一次，皆大欢喜，到项目验收时你就傻眼了：那花了几个月写的高达几尺厚的文档，怎么做出的系统，客户我都不会明白？你说当时客户验收时两天内能够消化这么多文档吗？这是客户的悲哀，也是我们的悲哀。如果我们有实力，我们能这样被动吗？我们一半的时间都在应付客户，而没有做本质的事情。前段时间客户要概要设计文档，时间紧，项目组缺人，让一个DBA突然进来，干了两周，做了上百页文档，然后交给客户验收，DBA就退出了，你说这样的概要设计有用吗？一句话，还是我们不够强势，没有力量去强势。<br /><br />离开的另外一个方面，就是待遇的问题。我倒不是说我的待遇差，其实我这一年多的待遇是比较高的，相比其它部门和大连其它公司，只是比起一年前降了1k多。我们公司工资分两块，一块是基本工资，一块是绩效。我的基本工资部分，和大连其它几家大公司的工资持平，而绩效往往有2到4k，这只是因为当时我做的那个项目很肥，不是决定于我的能力。当然以我的能力也能够拿那个价。但一个上千万的项目，做到最后竟然不赚钱，还可能赔钱，你们怎么都不信吧？部门很多项目都这样。<br />现在这个项目只有几百万，分的项目绩效不多（按项目报价的15%），我的绩效也自然就降下来了。这倒不是我离职的真正的原因，离职的真正原因是我干活很郁闷，成长太慢。我们部门资历高的很多，但他们一般都不写代码，一些人也不会写代码，觉得写代码是PG的活，他们用Rose画好各种图，生成代码的框架，让那些毕业生去填（我现在姑且不谈这种开发模式的成本高，设计和编码脱节、不利于人才成长）。<br />我现在的项目主要是有关工作流、业务流程的，不是那种简单的OA，技术这块现在风险最大。我觉得我绝不是一个喜欢逃避的人，但我的leader是部门架构师和项目PL，也许有点文人相轻，我觉得他对我缺乏授权，我没法发挥我的全部热情和能动性，我不可能按他的要求两天出个方案，一天定个架构（要是他有类似项目的经验就好了）。我始终认为，做一件事情，需要多长时间就是多长时间，不是我们主观决定的。也许我和他沟通问题很大。我也不怪他什么，项目太紧，他压力大。<br /><br />上面我说到待遇问题时，又扯远了。我们部门很多项目都是上面的情形：拿到一个大单子就不知所措。要知道，大单子往往不是增删改查，把Struts＋Spring＋Hibernate（SSH）摆乎摆乎就可以了。如果项目的架构只需用SSH就可以搞定的，是怎样的项目呢？反正我接触到的几个项目更关注于业务系统之间的集成和分解（业务架构），组件划分、性能、安全、异构平台等问题。我以前也做过用Struts+Hibernate就可以解决问题的项目，但这类项目不用这两个框架同样可以解决，只是一个工作量的问题，它们业务很简单。这些项目都不大，几十万的单子，一个公司没啥积累，随便招几个也可以忽悠过去。也许我这样说很消极，但国内大多数做项目的公司，遇到这样的项目，估计也就这样了。那些项目对于客户一般都不痛不痒，类似的电子政务项目往往就是一个政绩工程。但做大项目呢？这样的项目应该是客户的核心系统吧，这时候才到了考验人的时候。这类项目，就单说技术吧。一般有很多东西是可以重用的，譬如SSO、workflow、组织结构管理、权限管理、全文检索、树形组件、Table组件等等，太多了，不便列举。像前面四种，我们几个项目都用到，一个项目做一套，不说项目进度拉长，就是质量也很难过关。当然这些可重用资源还不一定是风险很大的。像我们，类似项目的框架搭建、规范很难都难以重用，一个项目组一个势力。<br /><br />如果大多数项目，都是重头再来，技术成本风险不说，业务风险也非常大。你说，这样的项目赚钱吗？当然了，这样做项目，短期内，对开发人员很有利，因为每个活都有挑战性，反正我是成长很快的，因为很多事情我就得独当一面，而且一个leader一个做事风格，我从中了解到很多管理风格。而且，你很清楚项目的风险在哪里，至少知道什么会把项目搞砸。一个公司项目管理的成熟标志之一，就是大多数人可以按部就班，职责分明。但这样规范的公司未必利于某些员工的成长，不过对降低公司成本非常有利。所以在我在这家公司的经历，是一笔很好的财富。<br /><br />如果项目不赚钱了，我也不想和公司领导谈什么待遇的问题。离开时，我对我们部长还有些歉意，因为我来公司这两年，确实没有给部门带来什么利润，因为项目是亏钱的。他也了解我这个人，知道公司留不住我。<br /><br />我们部门薪资还是有点竞争力的，特别是那些拿固定工资的，只是那些毕业没两年的不乐观，公司都认为它们开始一年是产生负利润。但我更觉得是公司没有充分挖掘他们。做国内项目，按对日外包那样分SE、PG，我觉得是很可悲的。如果说你是PG，就意味着你除了堆叠代码，啥都不会，也自然不会给你安排有挑战性的活。但对新员工的自学能力我也不乐观，很多人来公司一年多了，Servlet的生命周期都不清楚。他们很多人喜欢问我问题，也许是因为以前我给他们培训过，我大体知道他们的自学能力，替他们担心啊。 <br />当然了，业务系统到最后的编码，难度确实很低，即使是一个千万级的项目。别谈可维护性、可扩展性、灵活性，这些东西都是需要成本的，我们也做不好，我们只要满足客户的业务需求，通过验收、收回款项就可以了，我们不是在做产品。我这么说，只是出于无奈，PM无奈，公司高层也无奈。<br /><br />我无法改变这个现实，所以，我决定离开。常年在这种环境下工作，我担心我的激情会被磨灭掉，几个月前，我突然问自己：我能干啥？技术有意思吗？我是一个追求完美的人，我把工作当成自己的事业，我需要寻找那种自信和征服感。我们可能无法改变环境，但我们可以选择。<br /><br />运营一个公司或部门，像我们这样做传统企业项目的，好难啊。如果我是公司高层，我也感到无能为力。也不是说部门如何艰难，只是没有我期望的乐观。我在这家公司呆了两年，整体上还是对自己还是比较满意的，进步比较大，眼光视野也开阔多了，怎么说呢，公司也算是外包行业的前几位。我和同事、领导关系也都不错，总的来说还是比较开心，自由。<br /><br />算了，这次就写这么多吧。<br />期待我的下一个开始！
          <br/>
          <span style="color:red;">
            <a href="http://zwchen.javaeye.com/blog/123806#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 14 Sep 2007 14:25:53 +0800</pubDate>
        <link>http://zwchen.javaeye.com/blog/123806</link>
        <guid>http://zwchen.javaeye.com/blog/123806</guid>
      </item>
      <item>
        <title>JBPM源码浅析</title>
        <author>zwchen</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zwchen.javaeye.com">zwchen</a>&nbsp;
          链接：<a href="http://zwchen.javaeye.com/blog/123579" style="color:red;">http://zwchen.javaeye.com/blog/123579</a>&nbsp;
          发表时间: 2007年09月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          离职啦，工作交接中，记录一下。<br />就如同了解Servlet规范、Servlet容器设计和实现一样，学会一种workflow的建模、引擎设计和实现也是必备的。工作流这东西是业务系统的一个核心模块，现在的大多数企业业务系统大多数是业务驱动的，如新闻行业采编发、制造业的采供销、金融保险的审批等，协同OA就不用说了。BPM、ESB、SOA现在很火啊！<br /><br /><br />下面的总结肯定欠成熟，70%合理就不错啦，看到这篇blog的朋友，一定要批判接受哦。<br /><br />当前我指的JBPM是3.2版本，因为从JBPM2.0到3.0，其API从package到class都完全重新设计了，以及其背后的建模思想和架构。在2.0版本里，是按照Spring+Hibernate那种Transaction Script方式组织的，OO的概念比较弱，里面是大量的interface、impl、service。而3.0版本，完全按Domain Model方式组织，Hibernate透明持久化，它是我见到的O/R Mapping最优雅的应用。<br /><br />在当前的3.2版本里，其整体架构可以这么去理解：领域对象，如ProcessDefinition、ProcessInstance、Node、Token、Transition等，都是Rich Model，里面的方法主要是处理业务，以及建立领域对象之间的关联，持久化则完全放在XXXSession中，如TaskMgmtSession，GraphSession等，也可以认为这些XXXSession是DAO，负责处理持久化。另外，org.jbpm.persistence.db.DbPersistenceService这些类相当于最底层的数据库Helper类。总之，JBPM的技术架构非常清晰易懂，也是非常典型的Domain Driven Design，在这种架构中，分层的概念被弱化了。<br /><br />上面是从架构的角度看待JBPM设计，其引擎设计和实现，则隐藏在架构下。了解其引擎设计思想，我的建议是，先仔细读读JBPM的User Guide第四章Graph Oriented Programming，专门探讨流程建模的理论，里面附带了一个微型的JBPM实现，几乎包括流程建模的绝大部分，如顺序流、并行、分支等：<a href="http://docs.jboss.com/jbpm/gop/jbpm.gop.zip" target="_blank">http://docs.jboss.com/jbpm/gop/jbpm.gop.zip</a> ，我建议研读JBPM源码前，先把这个理解透，JBPM的流程引擎核心代码和它非常相似，包括类名，只是扩展了一些。<br /><br />我用代码统计工具统计了一下，JBPM源码总共4w多行，除去注释和空行，约2万6千行。需要我们hack的核心、比较难、代码多的类约40个（共400多），反正它花了我整四天的时间，现在基本都弄清楚了。我主要是通过一个请假流程的部署、创建、任务执行来动态debug、静态查看的。JBPM源码中最难读懂的那部分是引擎调度，也就是org.jbpm.graph相关的几个包，最重要的是GraphElement和其子类Transition等、Node及其子类Fork等、ExecuteContext和Token。而引擎调度这部分， JBPM附带了一个微型JBPM实现，我在前面介绍过。除了引擎调度，其它相关源码就非常简单了。<br /><br />在JBPM中，有很多API是供JBPM自身调用的，如流程定义文件中支持的Expression语言，脚本等（org.jbpm.jpdl.el.impl），我们不用理会。<br /><br />我们主要和下面三类API打交道： <br /><strong>JBPM环境的配置、service的管理、流程的部署和卸载：</strong>它主要体现在org.jbpm中，另外辅助包有org.jbpm.jpdl.xml、org.jbpm.configuration。<br />org.jbpm.configuration负责services对象的创建，相当于一个微型的IoC容器、对象工厂，负责services的生命周期管理，如加载、创建、调用和销毁，像Job调度服务、数据库持久化服务、异步消息服务等。需要说明的是，由于其package下的ObjectFactoryImpl也是一个IoC容器，和Spring的IoC容器是有相同的职责：对象的管理。所以在这种松耦合架构下，可以将JBPM和Spring集成，如业务系统和JBPM引擎的事务处理、对象管理、配置管理等。请参考Spring-Module开源项目。<br /><br />org.jbpm.jpdl.xml负责流程定义文件的解析，譬如XML文件的解析，相关领域对象的实例化。通过hack其源码和原理，我们可以在业务系统中自定义流程，让用户可以自己定义、变更流程。<br /><br /><strong>JBPM中领域对象：</strong>如Node、Token、ProcessInstance、TaskInstance等，它们有三个职责，一个是保持从DB中加载流程和任务相关的数据或将数据持久化到DB。第二，为各领域对象建立关联，方便实现透明持久化（复杂的领域关联在Hibernate的mapping文件里配置）。第三，就是处理业务规则，如引擎调度算法，但不负责持久化。<br /><br /><strong>JBPM中持久化领域对象的Manager，DAO：</strong>如TaskMgmtSession。它们主要是持久化领域对象，如session.save(ProcessInstance)；或是执行查询，如根据流程ID查询该流程实例，查询操作都是配置在hibernate mapping中的hql语句，如hibernate.queries.hbm.xml。但可能并不能满足我们的要求，譬如按时间段查询当前的流程实例，任务的分页查询，这样，就需要我们自己扩展这些DAO类。由于它们查询是只读操作，所以很容易，而且扩展几乎是必然了，因为要是按JBPM默认的，把所有的Result查询出来，再过滤，性能是个很大的问题，我们应该按需查询。<br /><br />--------------------------------------<br />下面按功能分类说明一下：<br /><strong>JBPM流程的部署和卸载</strong><br />JBPM流程的部署和卸载，无论是通过管理控制台还是自定义部署，最终都是通过JbpmContext的 deployProcessDefinition(ProcessDefinition)部署，而ProcessDefintion实例的创建，是通过调用ProcessDefinition的相关方法，如parseXmlResource (String xml)。<br /><br />ProcessDefintion实例的创建，有多种输入源，譬如XML字符串、XML文件、zip包，还有最抽象的Reader、InputStream。如果在用户的业务系统里面自定义发布业务流程，也最终是调用ProcessDefinition相关方法。但流程定义解析，最核心的只有一个类：org.jbpm.jpdl.xml包下的JpdlXmlReader，<br /><br />org.jbpm.JbpmContext：该类可以理解为Façade模式的实现，与流程相关的manager类可以通过它取得，如getGraphSession()、getServices()，它是获取其它服务的快捷方式，也算是一个delegate类。如果大家对Context的概念比较敏感，其类职责就很好理解，在Servlet容器里面也有ServletContext的概念，和它意思差不多。对一般的系统软件一般来说，Context往往建模成Container的上下文。在JBPM中，它还负责流程部署、加载、卸载。<br /><br /><strong>JBPM的任务管理</strong><br />JBPM和任务管理相关的类主要是org.jbpm.taskmgmt.def和org.jbpm.taskmgmt.exe，像任务创建、分配等。<br />和任务相关的最重要的有两个方面，一个是任务分配，另一个是和任务相关的表单。当然，任务查询和任务日志也很重要。<br /><br />任务分配：解决的是将任务分配给谁，它有静态分配和动态分配两种，前者是在流程定义文件里部署，后者是通过代码动态指定。它涉及到的概念有Actor，PooledActor，Swimlane，AssignmentHandler。在做demo时，譬如JBPM官方自带的例子webSale里，就是通过Expression静态部署任务角色的，如user(leo)，group(orderManager)，但它用到了JBPM的第三方组件Identity，其实通过Expression静态分配角色，本质上也是通过AssignmentHandler实现的，如ExpressionAssignmentHandler。<br />任务分配，一般比较灵活的方案是在流程的Swimlane里面部署自定义action，然后重用swimlane。另外一种方案是，在每个task里面部署AssignmentHandler实现类。<br /><br />任务相关表单：主要是org.jbpm.taskmgmt.def.TaskController，它是task scope下的表单字段，类似Servlet里面的HttpServletRequest的setAttribute()。如果是process scope下的表单项，是org.jbpm.context.exe.ContextInstance，类似于Servlet里面的HttpSession的setAttribute()。<br /><br />附带说一下任务查询，所有有关查询和持久化的操作，都集中在包org.jbpm.db中，如任务相关的TaskMgmtSession，要是这些find方法不满足业务要求，建议自己扩展。<br /><br /><strong>JBPM的流程日志</strong><br />JBPM的流程日志，主要是记录一些事件（Event），如流程创建、任务分配，它们在GraphElement的fireEvent时，譬如在Node.leave()（Token离开当前节点时）触发fireEvent事件（在该事件方法里执行自定义Action），同时记录日志。我们关心的日志主要有process、task、transition、signal四类，每个下面还有事件细分，如task创建和分配。通过日志，我们统计流程执行效率，也可以得到详细的流程步骤日志。<br /><br />日志的查询，请参考LoggingSession及其相关类。顺便说一下，所有的日志类都继承于ProcessLog，约20来个。JBPM已经声明的日志查询方法，可能并不能满足我们的要求，自行扩展吧。<br /><br /><strong>其它API</strong><br />JBPM API里有org.jbpm.web、org.jbpm.security等，前者负责在web容器启动时加载JBPM引擎，将当前Session的用户设置为任务的Actor等，后者负责安全相关的认证和授权。源码很简单，不多说了。我建议实现类似业务需求时，不妨参考其实现，但拿来用就会发现它太简陋了。
          <br/>
          <span style="color:red;">
            <a href="http://zwchen.javaeye.com/blog/123579#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 13 Sep 2007 15:04:24 +0800</pubDate>
        <link>http://zwchen.javaeye.com/blog/123579</link>
        <guid>http://zwchen.javaeye.com/blog/123579</guid>
      </item>
      <item>
        <title>JBPM阶段性工作总结</title>
        <author>zwchen</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zwchen.javaeye.com">zwchen</a>&nbsp;
          链接：<a href="http://zwchen.javaeye.com/blog/123322" style="color:red;">http://zwchen.javaeye.com/blog/123322</a>&nbsp;
          发表时间: 2007年09月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          快要离职了，工作交接期。但发现技术调研这种东西交接效率非常低啊。下面是自己写的一篇文档，算是做个备忘了。<br /><br /><strong>一、工作概述</strong><br />近一个月左右，对工作流，特别是开源工作流JBPM进行了一定的技术调研和尝试，现将工作总结一下。<br /><br />我主要的工作时间花在以下几个方面，它们也是学习、研究工作流的一般途径：<br />1、JBPM3.2.1官方UserGuide（21章）通读了几遍，包括官方的examples、forum、wiki、apidoc。这五份资料来源是我认为最重要的。<br />2、google（english）、Javaeye和csdn相关工作流技术文章和评论，特别是“银狐999”的工作流blog。<br />3、国内OA、工作流、BPM产品的演示和功能介绍，如joinwork，思维加速，西安协同，摩卡等。<br />4、xflow、osworkflow、Willow、agileFlow等国内外开源工作流了解。<br />5、几本重要的工作流、BPM相关书籍和workflow模式，最重要的两本书是《OReilly Essential Business Process Modeling》、《MIT Press - Workflow Management--Models, Methods & Systems》。 另外JBPM的UserGuide第四章Graph Oriented Programming里有一个jbpm.gop.zip下载包，它就是JBPM引擎的mini版，几乎涵盖有JBPM引擎的绝大部分，如流转、分支、合并、、并行、同步、异步、事件、Action、表单。<br />6、JBPM的一个请假流程从页面到持久化的整个demo开发（约花两周时间），例子来源于csdn上一个非常典型的例子，有顺序、并发、互斥、条件分支等情形。另外，特别针对JBPM源码进行跟踪调试（四天）。<br />7、对当前项目的若干Use Case的深入分析，如流程图表示、流程实现。<br /><br /><br /><strong>二、JBPM环境和开发</strong><br /><strong>JBPM开发环境</strong>JBPM我是从3.1.4版本开始研究的，但发现3.1.4版的designer在推荐的eclipse3.12下画流程图时，eclipse总是处理僵死状态，一个操作都要5s以上。无奈之下，下载JBPM3.2版本，该版本在eclipse3.1.2下designer无法正常使用。但在eclipse3.3，也就是官方刚出来的Europa版本下，其designer可以正常使用，但代码开发时，也是僵死状态，而在eclipse3.12下开发正常。所以，我现在的做法是，用JBPM的3.2.1版本，用eclipse的3.12做开发和调试，用eclipse3.3做流程可视化设计。另外，3.2.1对mail这类节点有支持。<br /><br /><strong>JBPM控制台</strong><br />JBPM的管理控制台从3.1.4到3.2.1有非常大的改进，如中文问题、界面、流程发布等。但在实际项目中，我们还是几乎无法使用，理由如下：<br />1、该管理控制台还是很粗糙，只有最基本的功能，没有权限、组织结构、细粒度的流程管理等功能，另外必须汉化。<br />2、其流程designer默认是生成JSF表单，也就是说整个管理控制台和流程开发最方便是JSF做表示层，这不符合我们当前的项目实际。另外，用自己的业务表，而不是JBPM自带的活表（数据库对应jbpm_variableinstance表），也就意味着JSF表单没法用上。<br />3、我们的流程存在大量中国特色的定制，如回退、临时流转、跳越，不可能将流程用JBPM的designer设计好，发布到控制台就ok这么简单。<br /><br />当前，我们的项目需要流程控制台，但应该是完全自己开发，可以借鉴JBPM后台的设计实现思想，特别是流程查看时的流程图显示；另外我们还需要table格式的详细流转过程。<br />一般来说，控制台做得很强大的工作流系统，都是standalone方式运行，而不是我们现在的embeded方式。<br />关于JBPM控制台入门知识，JBPM官方wiki有非常详细的介绍。<br /><br /><strong>JBPM的开发模式</strong><br />实际的JBPM开发，我觉得应该注意以下几个问题：<br /><strong>1、业务处理的位置  </strong>我们知道，在MIS系统，如OA项目中引入工作流，主要是将流程逻辑和业务逻辑分开，流程数据持久化到流程引擎表，业务数据持久化到业务表。这就涉及到业务逻辑在哪里处理的问题。在JBPM中，是在ActionHandler还是在Business Service中？<br /><strong>ActionHandler中：</strong>我们将业务在JBPM的回调接口ActionHandler实现中处理，将业务表单对象通过ContextInstance的setTransientVariables()传入，在ActionHandler中持久化，也就是说，ActionHandler是我们的业务处理主体，可以通过在Task实例中记录业务表单ID。另外，数据库的Connection可以通过ActionHandler的ExecuteContext参数取得。<br /><strong>Business Service中：</strong>这个Service就对应于用Spring框架时的Service，我们可以在service方法里面调用JBPM的API，如JbpmConfiguration.getInstance().createJbpmContext(); TaskInstance ti = jContext.getTaskInstance(tiid); 将业务数据都持久化到JBPM的活表里，这样只在一个数据库Conntection上，可以避免分布式事务的问题。<br />上面两种方式，第一种是我推荐的，其基本思想是将工作流引擎当成一个集成框架，一切以流程为主线。第二种是将工作流引擎当成辅助的第三方库。两种方式对系统的侵入性都非常大，无侵入性我认为不现实。<br />参考：<br /><a href="http://www.processdriven.org/process_liberation.html " target="_blank">http://www.processdriven.org/process_liberation.html </a><br /><a href="http://weblogs.java.net/blog/edgars/archive/2007/08/understanding_j_1.html " target="_blank">http://weblogs.java.net/blog/edgars/archive/2007/08/understanding_j_1.html </a><br /><br /><strong>2、业务数据的存储 </strong> 把业务数据持久化到JBPM的活表jbpm_variableinstance中，可以很容易地进行字段级别的权限控制，灵活的表单自定义，而且可以在JBPM的管理控制台上二次开发，将开发的工作量降到最低，而这是大多数商业工作流产品实现的目标。但是，活表对于实时的业务报表统计分析很低效，有时不可能，因为表单项是离散的，并且不是最重要的关注点。关注点可能是流程的执行效率统计，也就是流程数据统计。<br />成熟的工作流管理系统（工作流引擎只是其中一个组成部分）往往是一个任务或节点对应一个表单，这样很便于表单自定义，将流程设计、表单定义、权限控制、组织结构和任务分配一气呵成。我理解的表单，只是如同Struts里面的ActionForm，只是页面数据的收集和呈现形式，具体到这些表单怎么持久化，采用JBPM的活表或自定义的业务表均可，但我倾向后者。<br /><br /><strong>3、面向流程的MIS系统的开发过程  </strong>对于一般的MIS系统开发，很强调领域分析、系统设计，也就是大量的UML图。这样的系统，往往可以抽象为增删改查CRUD，可以按页面分配工作量，增删改查都是无状态的，也就是说开发“增”并不影响“改”，一个操作一个业务，各业务操作互不影响、耦合。但有清晰流程的系统就不同，每一个业务操作都是有状态的，譬如一个OA的发文流程，可能有十来个步骤，各级领导审核、审批、查阅，每一步的操作都影响后面的业务流向，而且必须有各业务相关人员协作才能完成该发文目标，这样通过CRUD方式去理解这个系统就无法理清业务，如果通过流程驱动方式去建模，那么事情就简单了。<br />这样，就引发了一个问题：流程驱动的MIS系统，怎么制定软件开发过程？如果大家看过工作流产品（关键字：工作流、OA、协同、BPM）的demo介绍，就会知道，工作流系统的开发，往往和流程设计、表单设计打交道，在我们的成果物中（RUP中是artifact、工件），没有OO的概念，领域分析让位于流程分析：难道我们真的需要一个请假单LeaveForm的Domain？做报表系统开发，应该也没有强调Domain吧？因为它是数据驱动，没有强调业务层。<br />所以，我认为，流程驱动的业务系统开发，不要将概要设计、详细设计往上面套，它们的重点往往没有放在流程设计和实现这个根本问题上。也许，概要设计、详细设计这种瀑布开发过程挺适合低端的外包项目，譬如对日的外包，将低端Coding外包给中国公司。前提是，别人的详细设计可以确定95％以上需求，需求不明确带来的风险很小。另外，在用JBPM开发过程中，也许业务主要写在JBPM这个框架的ActionHandler回调接口中，我们详细设计的顺序图中的call或sendMessage，不适合反映这种过程，因为ActionHandler的lifecycle我们无法控制。那么详细设计的意义何在？<br />那么，软件过程怎么定？我认为还是敏捷一点，只关注三点：用户需求（详细的用例文档和原型）、流程设计、流程实现。文档只集中在第一点。<br />我认为，参考基于成熟的商业工作流产品开发模式，就是我们系统的开发的模式。<br /><br /><strong>三、JBPM对常见流程问题的解决</strong><br />JBPM的API文档非常匮乏，但是，JBPM的源码内部有很多注释，其代码可读性非常强，核心代码我认为不超过1w行，引擎核心代码也许只有两三千行。另外，阅读源码，最好对UML活动图、Petri网、Workflow模式较熟悉，譬如Join. setDiscriminator()，如果不了解Workflow模式的Discriminator模式，该方法就不知所措。<br />Process本质上，只有两个对象：Node和Transition（节点和有向弧），只要这两类对象就可以完整绘出一个流程图，当然，Node有很多子类，譬如Start、End、Fork、Join、Decision等。<br />JBPM的过程调度，是通过Token在流程节点之间转移实现的。譬如TaskInstance.end()的时候，调用Token.signal()，在signal()内部，依次调用：Node.leave()，Transition.take()，Node.enter()，这三个调用依次引发如下三个event：node-leave，transition，node-enter，在event内部，就处理我们自定义的ActionHandler和记日志。从中我们可以看出，事件（event）处理和Token调度是分离的。上面的三个event是重复循环的，可以驱动流程向前进行：离开当前节点过渡进入下一节点。<br />上面就是JBPM的大致调度过程，清晰、简洁。<br />参考：<br />JBPM引擎架构：<a href="http://blog.csdn.net/james999/archive/2007/09/02/1769592.aspx" target="_blank">http://blog.csdn.net/james999/archive/2007/09/02/1769592.aspx</a><br />JBPM微型架构实现：<a href="http://docs.jboss.com/jbpm/gop/jbpm.gop.zip" target="_blank">http://docs.jboss.com/jbpm/gop/jbpm.gop.zip</a> <br /><br />下面我对JBPM对工作流中常见问题的解决方案总结一下，基本上都来源于网络，自己试验了一下，很可行。<br /><strong>1、互斥任务</strong><br />譬如，员工请假流程中，员工请假申请提交后，系统应该创建两个并发任务：员工取消和主管审批，只要任何一个任务结束，另外一个就应该结束。<br />一种实现方式是，在请假申请Node后Fork出两个Node，员工取消和主管审批，它们Transition 的ActionHandler里结束另外一个Node的TaskInstance。<br />另外一种实现方式是，在一个Node里创建上面两个Task，在Node节点里设置属性signal="first" end-tasks="true"。signal="first"指一个任务结束，当前节点就流转；end-tasks="true"指结束该节点时自动结束其它没有完成的任务。<br />参考：<a href="http://jbpm.group.javaeye.com/group/blog/59741" target="_blank">http://jbpm.group.javaeye.com/group/blog/59741</a> <br /><br /><strong>2、动态创建任务，会签或任务分派</strong><br />像会签这类动态创建任务的情形，用流程图很难描述，所以一般是通过代码手工创建，JBPM为这提供了很方便的接口。<br />JBPM的实现方式。在task-node设置create-tasks="false"，在该task-node的event-enter事件中，自定义ActionHandler，处理任务创建的工作。<br />说明：对JBPM的API用得得心应手，必须对其API设计实现、引擎思想有较深入理解，譬如Event机制、Token调度、Workflow模式等，其API绝对没有Servlet API那么简单，容易上手。<br />参考：<a href="http://www.cnblogs.com/amushen/archive/2007/07/03/804237.aspx" target="_blank">http://www.cnblogs.com/amushen/archive/2007/07/03/804237.aspx</a> <br /><br /><strong>3、循环节点，文件传阅</strong><br />在默认的JBPM的designer里无法画出指向自身的有向弧，可以先在该节点的XML流程定义文件里写出指向自身的Transition，这样在图形显示下就会出现指向自身的有向弧。当然，重复创建两个类似的节点，之间有往返有向弧也可以实现。<br /><br /><strong>4、并发子流程</strong>JBPM自身对子流程的支持不够灵活，如只能创建一个子流程（ProcessState.setSubProcessDefinition()而不是addSubProcessDefinition()）<br />一种解决方案是用流程的Hierarchy分级结构方式，请参考：<a href="http://jeffreyhsu.javaeye.com/blog/29917" target="_blank">http://jeffreyhsu.javaeye.com/blog/29917</a> <br /><br />...............<br />...............<br /><br /><strong>5、客户的Visio流程原型实现的探讨</strong><br />该流程原型，要求把JBPM的流程定义模块重新实现，有一定难度。但我认为，实现是完全可以的，但初步实现需要一个多人月的时间（以自己目前的能力）。<br />作为我个人的角度，我觉得Leader应该给开发人员充分的授权，信任开发人员，时间自由支配，定一个大致milestone就可以了。前段时间的技术调研太浮躁，一天一个方向，根本就没有调研深度。做一件事情需要多少时间就是多少时间，人为主观去控制，注定会失败的。<br />如果现在想按客户的要求实现，技术比以前的预想难多了，因为现在的流程定义是活的，相当于我们做了一个流程管理控制台和流程设计器。可以做，但风险大，不过，静下心来，是完全可以完成的，因为JBPM这部分相关代码只有几千行（千万不要忘了，JBPM只是一个naked流程引擎，不是工作流管理系统）。项目现在面临的一个问题是，前期开发有一个时间瓶颈，核心代码没有开发出来，后面的开发无法进行，以当前的管理模式，势必会让前期开发人员浮躁（自由的思想才会有深度，有创造力）。<br /><br /><strong>客户原型实现看法：</strong><br />流程定义和修改：JBPM有JpdlXmlReader，负责XML流程定义解析的，把该类和其关联类弄明白就差不多了，估计约两天时间，我花完整一天时间读过，不太难。<br />节点编辑，出口编辑：解析过程同上，<br />数据项编辑：利用JBPM自己的活表（TaskController相关），实现不是很难。<br /><br />如果按客户的方式做，做成功了，其它项目就很好复用，因为它就是做了一个通用的元框架，也算是拿做产品的要求来做项目。<br /><br />另外，如果不做成通用框架，解决现在项目中的若干技术问题难度都不大，如回退、串并行、版本控制、自由流、多子流程、强制跳转、自定义时限、权限控制、流程监控。但“提供自定义流程功能”，就是上面客户的要求，这个难度很大，和中棉项目自定义报表难度有的一拼（中棉项目自定义报表以失败告终）。<br /><br />就总结到这儿吧，Workflow、BPM是企业软件的趋势，以后还得努力啊！
          <br/>
          <span style="color:red;">
            <a href="http://zwchen.javaeye.com/blog/123322#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 12 Sep 2007 15:20:46 +0800</pubDate>
        <link>http://zwchen.javaeye.com/blog/123322</link>
        <guid>http://zwchen.javaeye.com/blog/123322</guid>
      </item>
      <item>
        <title>AIX学习总结笔记一</title>
        <author>zwchen</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zwchen.javaeye.com">zwchen</a>&nbsp;
          链接：<a href="http://zwchen.javaeye.com/blog/97390" style="color:red;">http://zwchen.javaeye.com/blog/97390</a>&nbsp;
          发表时间: 2007年07月03日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          公司项目用到AIX和Websphere（WAS)，由于我负责WAS的诊断和调优，该工作对AIX的理解和操作要求比较高。以前做Linux服务器管理挺顺利的，现在碰到这AIX的Shell，真的很不顺手，象Linux最方便的快捷键，竟然在AIX下都失灵了，换成Bash也不行，譬如我最常用到的：<br />TAB: 自动补齐<br />cd ~: 返回到主目录<br />ctrl+l: clear<br />......<br /><br />关于AIX快捷方式，先用<strong>set -o vi</strong> 来初始化一下输出吧，然后就可以用ESC+vi快捷键了。<br /><br />另外，Linux下的查看用户，创建用户，系统日志目录等命令和目录全变了，而且IBM的RedBooks也没有提供充分的资料，网上的资料也很有限，导致学习起来很困难。<br />如果知道哪个命令，想看详细信息，千万别忘了man哦，但是，不知道该用什么命令，就麻烦了，反正它的命令和Linux差别太大。<br /><br /><br /><strong>AIX启动</strong><br />1、加电自检<br />2、/etc/rc.boot 初始化逻辑卷管理器（LVM），激活根卷组（rootvg），检查安装root文件系统，配置其它设备。<br />3、/etc/init 进程号为1<br />4、允许 /etc/inittab下的各个条目。inittab就如同一个总调用接口，带动系统其它子命令，如cron、rc.*。 所以，自定义的自启动进程，可以放置在此脚本里。<br /><br /><strong>关闭</strong><br />shutdown<br />halt<br />reboot<br />init 0<br />上面的若干命令的参数，请参考man<br /><br /><strong>登录</strong><br />和用户登录的相关的几个核心文件如下，优先级从上到下：<br />/etc/environment<br />/etc/profile<br />$HOME/.profile<br />可以将自己定义的个性化设置加入上面的文件里，譬如定义一个alias cls为clear命令，把一个经常访问的超长路径加入alias，export环境变量，譬如java路径。当然，放置在上面的initab也不错，看要求了。<br /><br /><strong>系统管理</strong><br />试试AIX功能强大的SMIT（System Management Interface Tools），几乎所有的系统管理工作都可以交给它，不过类似Windows的界面很容易乱码，可以用putty试试。详细manual，请参考man smit<br />尽量还是用命令吧，反正我是不习惯。<br /><br /><strong>关于我在WAS诊断过程中最常用的几个AIX命令</strong><br />申明：详细用法，请一定要<strong>耐心</strong>参考man<br />示例如下：<br />topas： 查看系统当前最占资源进程、分页、IO等信息<br />netstat -an<br />ps -ef |grep java  取得当前的WAS进程，譬如JVM的参数，取得PID来kill出javacore heapdump等文件<br />find / -name java 查找特定文件，譬如WAS的server.xml文件<br />lsattr 显示、设置系统设备属性 譬如产生javacore文件，就要查看系统是否具备产生该文件的条件<br />svmon 分析虚拟内存 这个在Java OutOfMemory和系统性能出问题是有用。<br />vmstat 有关系统内核的统计信息，譬如内核线程、虚拟内存、磁盘、CPU等。<br />export 很多命令依赖于环境变量，譬如产生javacore文件就要export DISABLE_JAVADUMP=true<br />kill 用-3、-9等<br />nohup 结合“&”进程后台允许，Note:只有“&”有时不行的。<br />cron：job调度
          <br/>
          <span style="color:red;">
            <a href="http://zwchen.javaeye.com/blog/97390#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 03 Jul 2007 18:07:53 +0800</pubDate>
        <link>http://zwchen.javaeye.com/blog/97390</link>
        <guid>http://zwchen.javaeye.com/blog/97390</guid>
      </item>
      <item>
        <title>软件开发的一点感想</title>
        <author>zwchen</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zwchen.javaeye.com">zwchen</a>&nbsp;
          链接：<a href="http://zwchen.javaeye.com/blog/95422" style="color:red;">http://zwchen.javaeye.com/blog/95422</a>&nbsp;
          发表时间: 2007年06月29日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          这两天，遇到工作中的两个小问题，加深了我以前对软件开发的看法。<br /><br /><strong>一个是关于Firefox崩溃问题的处理。</strong><br />本来我一直用得好好的Firefox2.0突然打不开了，现象是只出现任务栏的button（见我重现问题的截图），或是要求我输入上网代理账号（公司内部不是匿名上网），但那个“确认”按钮怎么点击都无效。几个月前我遇到过一次，最后是被迫重装，但我喜欢的一堆plugin都得重新寻找、下载，包括收藏、使用偏好等，花的时间不亚于装个OS。现在咋办？虽然我尝试去研究firefox在“Documents and Settings”下的preference，并且google “firefox startup bug”等，但最后还是失败而返。<br />其实，现在最难的就是：<strong>问题发生在哪里？</strong>根据现象，我觉得问题应该是发生在Firefox初始化时，需要连接到网络，譬如检测firefox最新版。在定位问题后，我用firefox的安全模式（firefox.exe –safe-mode）登录，进入后去掉了代理设置。重启，ok，然后在“选项”里面重新启用代理，可以正常google了。但退出firefox后，重新启动，问题依然。<br /><br /><strong>怎么解决？</strong>也就是不用每次启动firefox时确认那个代理对话框。找个匿名代理不就ok了吗？我想到曾经用过CCProxy的二级代理功能，于是我在本机安装一个它的共享版（仅支持三用户），在CCProxy里面设置我的上网代理IP，账号、密码。再把firefox的上网代理设置成CCProxy的IP、端口，但用的是匿名上网（CCProxy每次随系统启动）。<br />问题搞定！<br /><br /><strong>另外一件事情是关于表格对齐的问题。</strong><br />一位同事用Word做表格排版时，一表格cell居中对齐，弄了半天都没好（见截图示例），其它都是以前别人弄好的，不知道为什么丢下这个：怎么让那个橘红色的文本上下对齐格式和其它几个一致？大家都知道，Word的工具、菜单项都好几百，还有很多在菜单没显示，需要“自定义”的，一个个漫无目的尝试挺费劲的。现在<strong>我们怎么去定位这个问题？</strong>我们一般会在“格式”菜单里面去找（抛开无分类的快捷键），但怎么试都不行。其实，仔细想想，让文字在table的cell里面定位，是调节文字本身，还是调节cell属性？如果是调节文字的话，我们就应该选择文字吧？大家也可以想想，Word工具条上的那个“居中”功能，是归属哪个菜单（当然，对于纯文字居中，和table的cell居中，功能是不一样的，类似于OO的多态）。<br />问题在我定位后，轻易就解决了。<br /><br />从上面两个示例，大家想到了一些共通点吗？我觉得有两个：<br />1、怎么去定位问题。<br />2、怎么去解决问题。这比定位问题容易。<br /><br />其实，在软件开发工程中，我觉得我花时间最多的，往往不是解决问题，而且寻找、定位问题，也就是常说的debug能力。大家觉得上面两个问题和软件开发关系大吗？其实，我觉得，软件开发、设计，和它们解决的是同类问题。<br /><br />软件开发，我觉得最重要的一种能力，就是抽象思维：寻找问题的共通点、规律，发现现象背后的本质。大家认同吗？<br />我又想，哪个学科不是这样呢？只是软件开发更突出点。
          <br/>
          <span style="color:red;">
            <a href="http://zwchen.javaeye.com/blog/95422#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 29 Jun 2007 10:53:29 +0800</pubDate>
        <link>http://zwchen.javaeye.com/blog/95422</link>
        <guid>http://zwchen.javaeye.com/blog/95422</guid>
      </item>
      <item>
        <title>Java线程安全系列（1）--Servlet线程安全</title>
        <author>zwchen</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zwchen.javaeye.com">zwchen</a>&nbsp;
          链接：<a href="http://zwchen.javaeye.com/blog/91088" style="color:red;">http://zwchen.javaeye.com/blog/91088</a>&nbsp;
          发表时间: 2007年06月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          刚才search的时候，竟然发现一篇我很熟悉的文章。仔细一看，哇，竟然是我很早以前写的一篇，被人匿名转载。我现在就干脆再转到我的blog大本营上吧，我觉得对Java新手还是有帮助（原文没有做任何更改，可能有bug，呵呵）。 <br />我很久以前的blog（<a href="http://chenzhiwu.spaces.live.com/" target="_blank">http://chenzhiwu.spaces.live.com/</a>），感觉发布技术文章特不方便，干脆就不用它了。<br /><br /><strong>概述</strong><br />在探讨java线程安全前，让我们先简要介绍一下Java语言。<br /><br />任何语言，如C++，C#，Java，它们都有相通之处，特别是语法，但如果有人问你，Java语言的核心是什么？类库？关键字？语法？似乎都不是。Java语言的核心，也就是Sun始终不愿意开源的东西：Java虚拟机的实现（不过sun公开了其Java虚拟机规范），也就有了BEA的JRockit，IBM的Jikes，Sun的Hotspot。<br /><br />Java的核心有两点，Java类加载（Java Class Loader）和Java内存管理，它们具体体现在Java类库的以下几个类：<br /><br />java.lang.ClassLoader（java.lang.Class）：我们调用的类，包括其接口和超类，import的类是怎么被Java虚拟机载入的？为什么static的字段在servlet容器里面可以一直生存下去（Spring容器中）？<br /><br />java.lang.Thread(java.lang.ThreadLocal)：垃圾回收是怎么进行的（垃圾回收线程）？我们的程序是怎么退出的？<br /><br />java.lang.refelect.Proxy（java.lang.refelect.Method）：为什么Tomcat、Tapestry、Webwork、Spring等容器和框架可以通过配置文件来调用我们写的类？Servlet规范、JSF规范、EJB规范、JDBC规范究竟是怎么回事？为什么它们几乎都是一些接口，而不是具体类？<br /><br /><br /><strong>Servlet线程安全</strong><br /><br />在Java的server side开发过程中，线程安全（Thread Safe）是一个尤为突出的问题。因为容器，如Servlet、EJB等一般都是多线程运行的。虽然在开发过程中，我们一般不考虑这些问题，但诊断问题（Robust），程序优化（Performance），我们必须深入它们。<br /><br /><strong>什么是线程安全？</strong><br /><br /><div class="quote_title">引用</div><div class="quote_div">Thread-safe describes a program portion or routine that can be called from multiple programming threads without unwanted interaction between the threads。</div><br /><br />在Java里，线程安全一般体现在两个方面：<br /><br />1、多个thread对同一个java实例的访问（read和modify）不会相互干扰，它主要体现在关键字synchronized。如ArrayList和Vector，HashMap和Hashtable（后者每个方法前都有synchronized关键字）。如果你在interator一个List对象时，其它线程remove一个element，问题就出现了。<br /><br />2、每个线程都有自己的字段，而不会在多个线程之间共享。它主要体现在java.lang.ThreadLocal类，而没有Java关键字支持，如像static、transient那样。<br /><br /> 一个普遍的疑问，我们的Servlet中能够像JavaBean那样declare instance或static字段吗？如果不可以？会引发什么问题？<br /><br />答案是：不可以。我们下面以实例讲解：<br /><br />首先，我们写一个普通的Servlet，里面有instance字段count：<br /><br /><br /><pre name="code" class="java">public class SimpleServlet extends HttpServlet

{
       // A variable that is NOT thread-safe!
       private int counter = 0;
       public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
       {
              doPost(req, resp);
       }

       public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
       {
              resp.getWriter().println("&lt;HTML>&lt;BODY>");

              resp.getWriter().println(this + " ==> ");

              resp.getWriter().println(Thread.currentThread() + ": &lt;br>");
              for (int c = 0; c &lt; 10; c++)
              {
                     resp.getWriter().println("Counter = " + counter + "&lt;BR>");
                     try
                     {
                            Thread.sleep((long) Math.random() * 1000);
                            counter++;
                     }
                     catch (InterruptedException exc)
                     {
                     }
              }
              resp.getWriter().println("&lt;/BODY>&lt;/HTML>");
       }
}</pre><br /><br />然后，我们通过一个html页面向该servlet发出三次请求：<br /><br /><pre name="code" class="java">&lt;HTML>

&lt;BODY>

&lt;TABLE>
    &lt;TR>
        &lt;TD>&lt;IFRAME src="./SimpleServlet" name="servlet1" height="200%"> &lt;/IFRAME>&lt;/TD>
    &lt;/TR>
    &lt;TR>
        &lt;TD>&lt;IFRAME src="./SimpleServlet" name="servlet2" height="200%"> &lt;/IFRAME>&lt;/TD>
    &lt;/TR>
    &lt;TR>
        &lt;TD>&lt;IFRAME src="./SimpleServlet" name="servlet3" height="200%"> &lt;/IFRAME>&lt;/TD>
    &lt;/TR>
&lt;/TABLE>
&lt;/BODY>
&lt;/HTML></pre><br /><br /> <br /><br />刷新页面几次后，产生的结果为：<br /><br />com.zwchen.servlet.SimpleServlet@11e1bbf ==> Thread[http-8081-Processor23,5,main]:<br />Counter = 60<br />Counter = 61<br />Counter = 62<br />Counter = 65<br />Counter = 68<br />Counter = 71<br />Counter = 74<br />Counter = 77<br />Counter = 80<br />Counter = 83<br /><br /> <br /><br />com.zwchen.servlet.SimpleServlet@11e1bbf ==> Thread[http-8081-Processor22,5,main]:<br />Counter = 61<br />Counter = 63<br />Counter = 66<br />Counter = 69<br />Counter = 72<br />Counter = 75<br />Counter = 78<br />Counter = 81<br />Counter = 84<br />Counter = 87<br /><br /> <br /><br />com.zwchen.servlet.SimpleServlet@11e1bbf ==> Thread[http-8081-Processor24,5,main]:<br />Counter = 61<br />Counter = 64<br />Counter = 67<br />Counter = 70<br />Counter = 73<br />Counter = 76<br />Counter = 79<br />Counter = 82<br />Counter = 85<br />Counter = 88<br /><br />我们会发现三点：<br /><br />servlet只产生了一个Servlet对象，因为输出this时，其hashcode都一样，<br /><br />servlet在不同的线程（线程池）中运行，如http-8081-Processor22，http-8081-Processor23<br /><br />Count被这三个doGet方法共享，并且并行修改。<br /><br /> <br /><br />上面的结果，违反了线程安全的两个方面。<br /><br />那么，我们怎样保证按照我们期望的结果运行呢？首先，我想保证产生的count都是顺序执行的。<br /><br />我们将Servlet代码重构如下：<br /><br /> <br /><br /><pre name="code" class="java">public class SimpleServlet extends HttpServlet

{

  //A variable that is NOT thread-safe!

  private int counter = 0;

  private String mutex = "";

 

  public void doGet(HttpServletRequest req, HttpServletResponse resp)

    throws ServletException, IOException
{

    doPost(req, resp);

  }

  public void doPost(HttpServletRequest req, HttpServletResponse resp)

    throws ServletException, IOException

  {

    resp.getWriter().println("&lt;HTML>&lt;BODY>");

    resp.getWriter().println(this + ": &lt;br>");

    synchronized (mutex)

    {    
      for (int c = 0; c &lt; 10; c++)
      {
        resp.getWriter().println("Counter = " + counter + "&lt;BR>");
        try
          {

          Thread.sleep((long) Math.random() * 1000);
          counter++;
        }
        catch (InterruptedException exc) { }
      }
    }
    resp.getWriter().println("&lt;/BODY>&lt;/HTML>");
  }

}</pre><br /> <br /><br />我们的输出结果为：<br /><br />com.zwchen.servlet.SimpleServlet@109da93:<br />Counter = 0<br />Counter = 1<br />Counter = 2<br />Counter = 3<br />Counter = 4<br />Counter = 5<br />Counter = 6<br />Counter = 7<br />Counter = 8<br />Counter = 9<br /><br /><br />com.zwchen.servlet.SimpleServlet@109da93:<br />Counter = 10<br />Counter = 11<br />Counter = 12<br />Counter = 13<br />Counter = 14<br />Counter = 15<br />Counter = 16<br />Counter = 17<br />Counter = 18<br />Counter = 19<br /><br />com.zwchen.servlet.SimpleServlet@109da93:<br />Counter = 20<br />Counter = 21<br />Counter = 22<br />Counter = 23<br />Counter = 24<br />Counter = 25<br />Counter = 26<br />Counter = 27<br />Counter = 28<br />Counter = 29<br /> <br /><br />这符合了我们的要求，输出都是按顺序的，这正式synchronized的含义。<br /><br />附带说一下，我现在synchronized的是一个字符串变量mutex，不是this对象，这主要是从performance和Scalability考虑。Synchronized用在this对象上，会带来严重的可伸缩性的问题（Scalability），所有的并发请求都要排队！
          <br/>
          <span style="color:red;">
            <a href="http://zwchen.javaeye.com/blog/91088#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 16 Jun 2007 23:19:24 +0800</pubDate>
        <link>http://zwchen.javaeye.com/blog/91088</link>
        <guid>http://zwchen.javaeye.com/blog/91088</guid>
      </item>
      <item>
        <title>真是个游泳的好季节啊</title>
        <author>zwchen</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zwchen.javaeye.com">zwchen</a>&nbsp;
          链接：<a href="http://zwchen.javaeye.com/blog/91072" style="color:red;">http://zwchen.javaeye.com/blog/91072</a>&nbsp;
          发表时间: 2007年06月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          刚刚从大连星海湾游泳回来，感觉好有活力啊！<br />也号召大家，特别是我们搞IT的辛苦劳动者，一起游泳吧，享受美好生活！<br />像往常一样，中午1点半下海，四五点上岸，当然啦，中途返回岸边，在沙滩上晒晒太阳。<br />去年是从五月初开始下海游泳的，到10月初一股寒气进入大连后就停止了。好不容易盼到现在啊，不过上周末游了两个下午，一周的精神状态都超级好。<br /><br />在碧绿清澈的大海里，躺在海面上，晒着太阳，看着碧蓝的天空，辽阔的大海，远处的小岛，那种美妙的感觉真的无法形容。<br />所以啊，我就一直等着早点进入夏天。大连的夏天不热，现在白天平均也就25度吧。整个夏天的晚上可能还要盖薄被子，用不着电扇。<br />就说游泳吧，一般我是每周日下午游，几乎从未间断。现在改为每周六、周日下午游。一般三小时左右，大约三公里吧。我特不喜欢在游泳池里游，虽然常年都可以。但那50米的反反复复，心里够乏味的。<br />不过，现在感觉海也是有点小。为什么呢？因为一般都是在海岸200多米处游，游到最远，也还是容易看清岸边。总感觉出不了星海湾那个圈子，虽然很大。<br /><br />我现在想啊，离海湾5公里左右的地方不是有四五个稀落的小岛吗？哪天，约上4个游泳爱好者，上午出发，下午返回，中午在小岛休息片刻。不过岛上可能没人，所以只能饿着啦。<br /><br />上周，我一个人出海，往小岛方向游啊游，估计离海岸1000多米左右吧，因为当天下午有海雾，只能看到海岸那边的高楼，所以就不敢继续前行了。<br /><br />游泳的感觉真好啊，无拘无束。
          <br/>
          <span style="color:red;">
            <a href="http://zwchen.javaeye.com/blog/91072#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 16 Jun 2007 18:45:27 +0800</pubDate>
        <link>http://zwchen.javaeye.com/blog/91072</link>
        <guid>http://zwchen.javaeye.com/blog/91072</guid>
      </item>
      <item>
        <title>IBM WebSphere Application Server 诊断和调优(二) </title>
        <author>zwchen</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zwchen.javaeye.com">zwchen</a>&nbsp;
          链接：<a href="http://zwchen.javaeye.com/blog/90810" style="color:red;">http://zwchen.javaeye.com/blog/90810</a>&nbsp;
          发表时间: 2007年06月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          上篇： <a href="http://www.javaeye.com/topic/74737" target="_blank">http://www.javaeye.com/topic/74737</a><br /><br />续写这篇文章，已经过去一个半月了。直到现在，系统一直运行平稳。<br />先说说我接手这项工作的经历吧：该项目大部分是06年10月就部署在客户那边了，到07年3月份，WAS宕机问题实在无法忍受，我才加入进来，前半年有另外一位同事断断续续处理，但对问题一直都无可奈何，而且项目负责人也没有引起足够的重视。可想而知，最后付出的代价是非常惨重的。在这近半年的时间内，服务器宕机63次。每次宕机时，WAS的JVM会dump出一个heapdump.phd文件(heap快照)，然后JVM就死掉了，当然，此时WAS也停止了响应。一般我们的做法是重启，最后是干脆AIX每天晚上定时重启。有时候一天还死多次。大家见附件的截图（all-GC.png）。这是我接手后，用IBM的分析工具得到的截图。对截图的分析，留给后面对应的部分吧。<br />服务器不稳定、宕机问题，拖延到最后，客户愤怒了，公司高层也害怕了，部门还专门成立了八人攻关组。当然了，我当时的压力也非常大，因为我是技术负责人，也就是实实在在干活、想主意的。<br />服务器诊断那段时间，从前到后，我们也是沿着一条线走下来，虽然最后发现很多路都走不通。现在就按这个思路，也就是时间先后一步步叙述吧。我想，大家如果也碰到类似应用服务器诊断，应该思路差不多。<br /><br />术语说明：<br />IBM Websphere Application Server：WAS，WebSphere本身是一个平台，产品家族<br />OutOfMemoryError：OOM，内存泄漏，内存溢出<br />Gabage Collection：GC，自动垃圾回收<br />Content Management System：CMS，就是给新闻类门户网站编辑们用的系统<br /><br />我们诊断大体上经历了以下几个阶段：<br />1、按Job调度线程池引起内存泄漏诊断：因为很多次OOM是发生在某个特定时候，譬如14：30、22：40左右。<br />2、按应用程序引起内存泄漏诊断：用JProfiler等工具探测：因为总是发生OOM。<br />3、分离WAS怀疑有OOM的应用：因为每个WAS应用太多，20来个，混一起没法定位。<br />4、用IBM官方heap、GC分析工具。以及和IBM技术支持联系。WAS、AIX参数优化。<br />5、隔离出WAS超级恶魔程序：一个CMS产品。<br />6、WAS、AIX参数优化、设置。<br /><br />我们走到第5步时，才出现效果。计算一下，那时已经过去一个月了。服务器宕机、系统不稳定，在这个验收的时候，客户已经忍无可忍，以致后来的每一次行动都得胆战心惊得去做。<br /><br /><strong>一、按Job调度线程池导致内存泄漏诊断</strong><br />因为从我们WAS的日志(默认是native_stderr.log)来看，最近半年的宕机时间都有一个明显时间规律。见附件截图Job1-1.png。<br />我想，做过Java服务器性能调优的朋友，都知道在Web容器里面启线程池是个不太好的做法，因为Web容器本身有一个线程池，譬如Servlet线程池（Tomcat默认起25个），而自启的线程池很容易导致Servlet线程管理混乱，最终导致GC问题。我们的现象似乎和那很符合。如果我们沿着这个思路做下去，具体怎样实施呢？<br /><br />我们的WAS上部署了20个左右的Web应用，譬如Lucene全文检索、B2B行业数据同步等，都是通过Quartz的Job调度做的，当然还有很多其它调度。当时，由我负责，通知相关负责人，将定时调度暂时去掉。观察了几天，后来发现问题依然存在，不过时间有点随机了。<br />     不过，最后还是发现OOM不是由Job调度引起的。<br />  也就是说，我们这个方案是失败的。而且，我们的很多想法都是臆测的，没有可靠的根据，也没有方向，再加上我是第一次处理这种问题，这导致后来查找问题的艰难。但是，仔细想想，我们又能拿什么做依据呢？出现OOM错误，我想大多数人想到的，除了JVM参数设置，就是内存泄漏。其实，OOM发生有很多种情况，在IBM、Sun、BEA等不同虚拟机上，因为GC机制不一样，所以原因一般都不同，容易定位难度也不一样。下文会谈到。<br />     于是，我们干脆釜底抽薪分析问题吧：用JProfiler检测。<br /><br /><strong>二、按应用程序导致内存泄漏诊断，JProfiler检测</strong><br />   如果遇到OOM问题，我想大家都会想到内存检测工具，现在最可靠的还是下面三种分析工具：Borland 的Optimizeit Suite，Quest的JProbe，ej-technologies的JProfiler。但面临三个问题：<br />1、三个都是商业产品，公司暂时没有买，必须自己下载，而且要找序列号。<br />2、工具必须支持AIX5.3＋JDK1.42＋WAS6.0，不是Windows平台。<br />3、工具必须在客户真实环境下部署，对客户的业务不能有冲击，也就是说部署测试工具前，必须做个大量测试，对工具非常熟练，遇到意外可以立即恢复现场。<br />Note:项目上线后，而不是测试或试运行阶段遇到此类问题，非常考验人；另外一个，就是性能和可伸缩性问题，很可能把整个项目给毁了。<br /><br />当我决定要这么做后，就立即动手查阅这些工具的官方文档，用emule下载，最终都下载到了。试用后，最终选择了JProfiler4.03，比起其它工具，它界面美观、清晰、功能强大、集成度高(Heap,Memory,CPU,Thread都统一了)。另外，JProbe没有AIX版本，这也是放弃它的一个原因。<br /><br />JVM的Profiler原理，都是通过JVM内置的的标准C语言Profiler 接口收集数据，然后通过Profiler工具的客户端展现。也就是说各厂商的Profiler工具，都有两个部分，一个部分是Profiler Agent，和JVM绑定，负责收集JVM内部数据，譬如方法调用次数、耗费时间等；另外一个部分就是Profiler front-end。通过Profiler工具的自定义local或remote协议传输到front-end，其实，我们最常用的JavaIDE的debug功能就是在此基础上的（JPDA）。（JProfiler的截图<a href="http://www.ej-technologies.com/products/jprofiler/screenshots.html" target="_blank">http://www.ej-technologies.com/products/jprofiler/screenshots.html</a> ）。<br />下面是Sun官方文档：<br />JDK1.42及以前是JVM PI：<a href="http://java.sun.com/j2se/1.4.2/docs/guide/jvmpi/jvmpi.html" target="_blank">http://java.sun.com/j2se/1.4.2/docs/guide/jvmpi/jvmpi.html</a> <br />JDK1.5是JVM TI：<a href="http://java.sun.com/j2se/1.5.0/docs/guide/jvmti/jvmti.html" target="_blank">http://java.sun.com/j2se/1.5.0/docs/guide/jvmti/jvmti.html</a><br />具体到JProfiler的配置上，专门针对JDK1.4和1.5的JVM配置差别很大。<br />  <br />我用的JProfiler是4.31版本，透露给大家一个万能序列号吧(这东西不太好找)，对各版本应该都支持。深入了解Java，这类工具是不可少的：<br />Name: License for You <br />Lincese Code: A-G667#42616F-10kg1r134fq9m#2217<br /><br />为了保证真实环境的检测成功，我做了大量的试验，譬如：<br />1、Windows系列的本地、远程测试。<br />2、AIX的远程测试。<br />3、Tomcat5.0、WebLogic8.14、WebSphere6.02，以及上述两种方式的组合测试，排列组合，场景不下10个。<br />当时也参阅了大量JVM文档，JProfiler官方几百页英文文档，辅助的JProbe对照。而且也制造过内存泄漏造成的OOM场景。<br />当然，要是在几个月前，在客户那边部署的测试环境时，就进行测试该多好啊。<br /><br />在公司内部，我用JProfiler测试了我们当时部署的几个应用，没有发现内存泄漏，所以，我们最怀疑的是就是CMS系统。因为出问题的那个WAS上它占去了90％的负荷（我们有多台AIX、WAS服务器）。该CMS超级庞大，感觉著名的赛迪网就用它，当时该CMS厂商给我们部署都花了快一个月。所以再重新部署一套测试环境也挺困难。另外，CMS提供商不给lisence。现在测试，客户早就对我们恼火了，当然不怎么配合，这对我们工作的开展就有很大的挑战。<br /><br />在大致可以确定万无一失的情况下，我们最终决定在客户的真实环境下测试。也就是让JProfiler的agent端直接在WAS的JVM里面启动（北京IDC），然后远程（大连）监控。<br />本来该模式在另外几个应用的测试都通过了（因为北京IDC那边好几台AIX服务器）。但一部署上，客户的一些编辑用CMS时就感觉超级慢，尽管我们用了JProfiler的最小负载模式。半个小时后，客户实在无法忍受，打电话过来，又把我们部长和经理训了一顿，还要写书面报告。我们被迫马山中止测试，恢复现场。<br /><br />虽然JProfiler也支持客户那边的环境，但还是有bug，至少负载一高就有严重的性能问题，几乎导致系统挂起，这是我当时没有料到的。JProfiler一启动，WAS的启动时间就由原来的3分钟降到10分钟，而且系统响应明显变慢，我们具体的环境如下（排列组合恐怕不下20种）：<br />1、AIX5.3，Power PC64位（不是32位）<br />2、WebSphere6.0<br />3、IBM JVM1.42<br />4、Remote 模式<br /><br />	我后来仔细读了一下JProfiler的changeLog，发现对上面的环境支持不够也很正常，因为官方在最近的4.3.x版本下陆续有对IBM JVM和Websphere6.0的features和bug fix：<a href="http://www.ej-technologies.com/download/jprofiler/changelog.html" target="_blank">http://www.ej-technologies.com/download/jprofiler/changelog.html</a> <br /><br />进行到这一步，我忽然觉得无计可施了<img src="/images/smiles/icon_sad.gif"/>，此时已经过了三周。<br />上面的策略，我认为是很正统的处理方法。谁怪我们当初项目上线时没有进行充分的测试呢？其实，这类测试没做也正常，OOM这类问题谁都无法预测。<br /><br />到这个时候，我想肯定有人会问我？你知道导致JVM的OOM有几种情况吗？在当时，我想到了以下五种：<br />1、JVM的heap最小、最大值没有设，或不合理。<br />2、JVM的maxPermSize没有设置（这个IBM的JVM没有，一设置JVM就起不来）。<br />对于Sun和BEA的JVM，以上两种参数设置，可以排除90％以上的非程序内存溢出导致的OOM。<br />3、程序内存泄漏<br />4、有的JVM，当在80%的CPU时间内，不能GC出2%的heap时，也发生OOM（IBM的JVM就是，但我没有验证）<br />5、JVM本身内存泄漏（JVM有bug不是不可能）<br /><br />现在的难题是，如果是那个可怕的CMS程序本身有内存溢出，在产品环境下，我们怎么去验证？我们自己开发的10来个web应用，测试并不是很难，在公司测试都可以。但是，我现在最想解决的，就是CMS测试的问题。而且，在我们那种环境下，该CMS产品供应商并没有透露成功案例。<br /><br />其实，最后发现，并不是内存泄漏造成的，因为我们的heap走势都很平稳。纳闷的是，有1000M的heap，每次在heap只被占用400来M时就发生OOM，没有任何预兆。大家猜猜，会是什么原因<img src="/images/smiles/icon_rolleyes.gif"/>？这个问题我到后面相关章节再说吧。<br /><br />既然我们所有的矛头都指向那个可怕的CMS系统，现在就是考虑隔离的问题。如果我们验证这个问题是CMS造成的，那么大部分责任就应该由CMS厂商承担<img src="/images/smiles/icon_wink.gif"/>。<br />既然CMS我们不敢移（费劲，而且客户在正式用），那我就移我们开发的10来个web系统吧。<br /><br /><strong>三、移出除CMS系统以外的所有应用</strong><br />说起来容易啊，做呢？ 隔离（移动）工作由我负责，具体涉及到10来个相关负责人。<br />转移工作，必须处理好很多问题，就说几个印象最深的吧：<br />1、某些应用，如Blog和BBS，都涉及到文件、图片上传目录和产品本身的环境，如 JDBC连接池、Cache位置。<br />2、目标服务器本身的环境，WAS安装环境、网络等。<br />3、移植时的先后顺序、调度，各应用内部本身的约束关系。<br />4、移植后的测试。<br />当然，还有一个最严峻的问题，客户允许我们这么做吗？对它们目前运行的系统有多大影响？风险如何评估？<br /><br />这个工作持续了一天，已经完成了80％的工作，到第二天，客户又恼火了：WAS又宕机了。<br />为什么？这确实是WAS的一个bug：WAS的后台随便一操作，heap就会突然上升几百M，导致JVM内存不够。不过WAS撑住的话，过半小时后就会降下来，我估计是WAS后台对用户操作状态、文件都缓存到Session里面。你们可以检查类似这样的一个文件夹：d:\IBM\WebSphere\AppServer\profiles\AppSrv01\wstemp，我不知道为什么WAS不主动去清除它，它偷偷的就上升到几个G，系统硬盘可能不久就后就会空间不足，WAS莫名迟缓、最后死掉。听过WAS6.0以前这个目录更夸张。大家见我附件的截图WAS_Console.png那个尖峰。<br /><br />咋办？经理也已经不敢让我们继续铤而走险了。这个方案最终又以失败告终<img src="/images/smiles/icon_sad.gif"/>。<br /><br />不过，最后我们还是发现问题出在CMS上。我们以前把这个问题向CMS技术支持反映，有大量依据和现象，并且把相关日志都给它们。过了两天，他们最后竟然只回了一句话“从给我的两个日志来看，没有找到任何与XXX有关的东西....”。TMD！我真的很生气<img src="/images/smiles/icon_twisted.gif"/>，它们的产品都折磨我们半年之久了。不过，看他们对IBM的WAS和JVM也不懂，我也就不想再说什么了。下面是我的邮件，公司机密部分都隐去了：<br /><br /><div class="quote_title">引用</div><div class="quote_div">   附件是我们这段时间服务器宕机的日志。我们用IBM Pattern Modeling and Analysis Tool for Java Garbage Collector Version 1.3.2分析了一下虚拟机日志，没有发现是内存泄漏导致；用IBM HeapAnalyzer Version 1.4.4 分析heap文件，也没有发现很可疑的内存泄漏。<br />   我想以前你们也这样做过，现在我们分析错误日志，发现有一个现象，在宕机时，总是找不到文件，我看就是Websphere或是AIX IO资源不够，不知道是什么导致的。但是，我们自己的应用，基本上没有什么IO，除了一次load几个配置文件。不过，我觉得你们WCM的IO操作挺多的，不知道你对日志有什么新的发现。<br />   客观的说，这几个月来，宕机那台服务器，除了你们的XXX，就以论坛和blog为主，而且他们都是开源的。在频繁宕机的06年11月份，我们的论坛和blog还没有上线。现在我们不得不每天晚上11点定时重启，但这也不是长久之计。<br />   现在，我们进行分离遇到很大阻力，原来想把你们的XXX单独分离出来，在当前的环境下，不是很现实，如安装、测试（负载、定时服务），所以现在分离我们自己的应用，但当前在产品环境下，客户方阻力也很大。<br />   希望尽快能够得到你们的问题建议和方案。</div><br /><br />  文中说到了IBM的两个分析工具，这也是我们后来的救星：我们就是需要这种<strong>离线分析</strong>工具，因为<strong>实时检测</strong>已经证明不现实。但我始终对该分析出来的结果抱怀疑态度，直到我去深入IBM的JVM以及和IBM的技术支持交流......<br /><br />   柳暗花明啊<img src="/images/smiles/icon_smile.gif"/>，至少看到了一点希望，不过最后我们还是失望而返。<br /><br /><br /><strong>四、用IBM的HeapAnalyzer和GarbageCollector检测</strong><br /><br />找到这两个工具，已经是够费劲了，因为以前找的IBM HeapRoot工具，让我对这类工具很失望。而且，这两个工具，只有在IBM的Techinical Support网站能够搜索到，但很不容易，因为那两个工具，并不是象IBM的Websphere产品那样宣传，它只在IBM Techinical Support文章的某些角落里出现。要知道，Techinical Support是IBM很重要的收入来源，这类文档，他们并不会让你很轻易就拿到，比起BEA WLS的支持网站dev2dev差远了。<br />具体诊断细节我就不详述了。我认为，IBM的WAS或JVM出了性能和OOM问题，这两个工具是最有效的，而且是离线分析工具，比起那些实时Profiler工具，某些场合有绝对的优势：譬如我们目前的产品环境，你只能分析宕机后的日志，实时分析前面已经验证是不可行的。<br />从日志分析，我们最终得出结论，我们购买的CMS系统有严重的碎片（大对象）问题，而该问题是OOM的罪魁祸首，而且IBM工程师也得出了同一结论。不过，在起先我们得出这一结论一周后，我还始终不相信heap碎片会导致OOM，直到IBM工程师总是向我强调。<br /><br />我想很多人也是不太相信，因为大多数人用的都是Sun的JVM，譬如Windows、Solaris上的hotspot。而且，Sun JVM出问题，如果是配置的问题，一般通过配置heap最大最小值，以及maxPermSize都可以解决。Heap碎片导致的OOM，只有BEA的JRockit和IBM JVM上发生，不过JRockit有专门文档说明，而且很容易找到（就在jdk的文档里面）。<br /><br /><strong>配置heap最小最大值</strong>，我想大多数人都有经验。对于Sun的JVM来说，一般可以设置heap最大最小值一致，也是推荐的做法。因为它的GC策略默认是复制、分代算法。也就是说，它会将heap分成不同的几个区，譬如Solaris JVM中最上面有两个大小相等的区。GC时刻，将一个区的存活对象复制到另外一个对等区，垃圾对象就算遗弃了。这样在heap里面，就不存在碎片问题。另外，根据Java对象的存活期不同，将之转移到不同的区（Tenured区），存活最长的在最底部（火车算法），这也就是分代模型。具体请参考官方文档：<a href="http://java.sun.com/docs/hotspot/gc1.4.2/" target="_blank">http://java.sun.com/docs/hotspot/gc1.4.2/</a> <br /><br /><strong>对于maxPermSize（Permanent Generation），</strong>主要和那些加载到JVM里面的Java Class对象相关，它的空间不是在Java Heap里面分配。如果你当前的heap有1000M，permSize是200M，那么JVM至少占用1200M。<br />在这个空间内的对象的生存期和JVM是一样的，譬如JDK的核心类库，它们被System Classloader加载到JVM的Method Area（方法区）后，就不会被GC掉的，这些对象一般是Class对象，而不是普通的实例对象，也就是JVM的元数据。我们在用反射时经常用到它们。所以，对于现在象Spring、Hibernate这些框架经常通过反射创建实例，可能对maxPermSize要求就大了，缺省的64M很多时候是不够的，特别是对于应用服务器里的应用，象JSP就会产生和加载很多classes。不过，如果是它导致的OOM，一般会有类似 perm size提示。<br /><br />但是，对于IBM的JVM，情况就完全不一样。它的默认GC策略并没有采取复制、分代。这个可以从GC日志分析出来。它不像Sun的JVM那样，有个单独的方法区，它的方法区就放在Java Heap里面。JVM规范里面并没有要求方法区的必须存放的位置，因为它只是一个JVM实现问题。<br /><br />在IBM的JVM里面，这些对象一般分配在称为k-cluster和p-cluster里（cluster又是属于Heap），而后者一般是临时在heap里面申请。并且，这些cluster是不能GC，或是被移动重排的（Compact过程）。这就导致Java Heap里面就如同马蜂窝，但不同的蜂孔又不能合并，于是，当我们程序里面产生一个大对象，譬如2M的数组(数组必须分配在连续的内存区)时，就没有可分配空间了，于是就报告OOM。这些不能被移动的cluster就称为所谓的碎片。此时，JVM的Heap利用率可能不到50%。<br />当然，通过一定时期的GC日志，可以计算出cluster的合理大小（专门在Java Heap的底部），另外，还可以为这些大对象专门分配大对象区的（超过64k的对象）。<br /><br />通过上面的理论介绍，我想大家一定知道了为什么IBM的JVM里面不推荐heap的最大最小值相同，因为这样碎片问题会非常严重：如果我们每次大对象申请内存时，heap都扩展5%，譬如50M，碎片问题很大程度上可以避开，程序性能也高些（寻找可用空隙和分配耗时，以及每次GC时间拉长）。<br />以上的具体阐述，请参考我在上文推荐的几个URL，另外再推荐三个宝贵的链接：<br /><a href="http://www-1.ibm.com/support/docview.wss?rs=180&context=SSEQTP&q1=fragmentation&uid=swg21176363&loc=en_US&cs=utf-8&lang=en" target="_blank">http://www-1.ibm.com/support/docview.wss?rs=180&context=SSEQTP&q1=fragmentation&uid=swg21176363&loc=en_US&cs=utf-8&lang=en</a><br /><a href="http://www-900.ibm.com/cn/support/viewdoc/detail?DocId=2447476A10000" target="_blank">http://www-900.ibm.com/cn/support/viewdoc/detail?DocId=2447476A10000</a>（IBM 技术支持告诉我的，太重要了！）<br /><a href="http://www-900.ibm.com/cn/support/viewdoc/detail?DocId=2847476B08000" target="_blank">http://www-900.ibm.com/cn/support/viewdoc/detail?DocId=2847476B08000</a><br /><br />我想大家应该会问：<strong>我怎么能够肯定我的OOM问题是heap碎片造成的呢</strong>？下面的方法可以验证。<br />在OOM发生时，JVM会产生一个heapdump文件。然后用GarbageCollector分析出该OOM发生时刻，JVM去申请的空间，譬如约235k。此时，你再用HeapAnalyzer去分析此时的heap快照里面的gap size大小（空隙大小）和各自的可用数目。你会发现，大于235k的空隙个数为0。这就是碎片导致OOM的证据。<br /><br />另外，有人会问：<strong>我怀疑我的OOM是因为程序内存泄漏造成的，怎么去验证</strong>？<br /><br />你可以用HeapAnalyzer分析发生OOM时刻的heap快照，工具会罗列出哪些对象怀疑有内存泄漏，譬如Cache对象都非常大（但你可以确定它不是内存泄漏）。另外，分析这次宕机（从这次虚拟机启动到宕机这段时间）的heap走势，如果曲线明显是向上倾斜，也就是那种典型的内存泄漏图，就有可能是内存泄漏。当然，还必须结合heap快照。<br />内存持续上升在JVM开始一段时间很正常，因为JVM对第一次访问到的Class 对象，譬如一个典型的Web应用，就有jdk的class、Spring或Hibernate的class对象，它们都会被缓存下来(ClassLoader原理)，一般均不会被GC。当大多数class对象缓存差不多（当然还可能有一些Singleton对象，不过不怎么占分量），JVM的Heap就平稳了，呈一水平波浪或锯齿线。<br />如果可以用JProfiler这类工具实时监控，就更容易确诊了。<br /><br />经过一番周折，我们终于看到了一线希望了<img src="/images/smiles/icon_smile.gif"/>。<br /><br />在一定的准备后，我们决定对WAS进行性能调优了。WAS的调优参数，可以分为两个部分：JVM级别和WAS级别：<br />JVM：主要是GC和Heap。<br />WAS：Thread Pool，JDBC DataSource。<br />当然要调节，你需要明白你的目标是什么，调节依据是什么，怎么计算，绝对不是凭空想象的，譬如heap最小值1024M，日志证明，该参数非常不适合我们的环境。具体细节，留给后文吧。<br /><br />战战兢兢地，中午12:00，我们给产品环境下的WAS调节参数、重启，同时优化了AIX的IO相关参数。<br /><br />我试着设置了一下JVM的k-cluster和p-cluster。下午15:00左右，WAS挂了，AIX也挂了。这下麻烦可大了。我们都慌了，马山客户的老总就来电话了，一阵哗哗啦啦。实在无奈，让客户那边工作人员通知机房（服务器托管处）工作人员重启AIX。我也不得不强行更改刚才的参数，立即设为另外一个值。<br />其实，我把那个两个cluster值确实设置太大了，我把它们设置为推荐值的5倍，譬如p-cluster是65k×110%×5。另外一个愚蠢的设置就是把最小heap设置为2048M(AIX有4G内存)。<br />后来我恢复到约正常的值，也就是去掉那个cluster的5，另外分配了一个30%的大对象区（如果1000M的heap，就是700M＋300M）。<br /><br />就这样，系统持续正常运行了三天，以前可是一天一down。当在三天后再次宕机时，我们都没有自信了<img src="/images/smiles/icon_evil.gif"/>。不得不通过AIX的cron，继续每天深夜11点的WAS定时重启。<br />不过，那次宕机，包括以后的几次宕机，<strong>再也没有出现OOM错误了</strong>，但系统依然不稳定。虽然我可以说OOM问题解决了，但领导和客户需要的并不是这种结果。<br /><br />其实，在这个时候，我们已经发现我们系统的四大问题：<br />1、WAS和JVM参数：OOM问题<br />2、AIX的IO和Paging Spacing不足：AIX日志后来显示错误<br />3、AIX的WAS分区空间不够：WAS的日志膨胀一周就把那个opt分区塞满了。<br />4、应用程序的JDBC连接池：我们20来个应用，一个20 connections，DB2数据库有时被撑死。<br /><br />也就是说，我们最初在客户那儿部署时，用的默认值根本不行。而且，部署涉及多人，人员之间出现断层。如果我们只是按OOM，无疑是走入死胡同，必须全局考虑！<br />但是，项目组实力薄弱，公司范围内就没有对AIX精通的。不过项目组原来有一个搞银行系统，在AIX下开发，就他熟悉些。我当时对AIX也比较陌生，你们从Linux转到AIX，你就知道它有多别扭了。命令都自定一套（也许因为是Unix元老吧），那个shell也超级别扭，而且参考书特少。不是自诩，我两年前负责一个高负载的Linux服务器管理一年多，也是玩得很转的。<br /><br />就这样，他负责AIX的相关问题，我负责WAS相关的。<br />但是，现实环境，已经不允许我们再试验下去了<img src="/images/smiles/icon_sad.gif"/>。我们必须找到一条绝对可靠的对策！<br />这就是下文的CMS系统大迁移，服务器再次优化。<br /><br /><strong>文章太长（上万字），我把剩下部分发表在回复贴里面吧。</strong>
          <br/>
          <span style="color:red;">
            <a href="http://zwchen.javaeye.com/blog/90810#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 15 Jun 2007 18:16:30 +0800</pubDate>
        <link>http://zwchen.javaeye.com/blog/90810</link>
        <guid>http://zwchen.javaeye.com/blog/90810</guid>
      </item>
      <item>
        <title>从分布式系统的角度看REST</title>
        <author>zwchen</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zwchen.javaeye.com">zwchen</a>&nbsp;
          链接：<a href="http://zwchen.javaeye.com/blog/83960" style="color:red;">http://zwchen.javaeye.com/blog/83960</a>&nbsp;
          发表时间: 2007年05月28日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          原帖：<a href="http://www.javaeye.com/topic/82227" target="_blank">http://www.javaeye.com/topic/82227</a><br /><br />为什么有分布式的需求？<br />我觉得最主要的还是做<strong>EAI</strong>（企业应用集成），以前我们做企业应用，一般都是孤立系统，譬如公司内部独立系统。但经过几年的发展，企业发现这些信息孤岛的整体运作效率很低，譬如人力资源系统和项目管理系统的用户是独立的，现在要进行整合。当然，EAI更多是企业的核心系统的整合，譬如制造业企业的供应链系统。<br /><br />怎么整合？当然，要是开始实行像ERP系统，统一数据库恐怕就没有这些问题。另外，要把那些信息孤岛都抛弃重做，能够达到理想的效果吗？考虑到各种风险，干脆取一种折中吧：EAI。<br /><br />实现EAI有很多种方式，在JavaSE方面，大家看看附件Java API的一张图：Integration API：RMI、JDBC、JNDI、CORBA。如果体现在JavaEE，就是EJB了。<br /><br />现在在Java领域搞EAI，还是主要三种方式：EJB、JMS、Web Services（SOAP和REST）。去年年底，我做一个地区门户网站内部的集成，就用REST，集成的语言有PHP、Java、Ruby。但一直没有解决一个问题：事务。<br /><br />现在Web Services（WS）为什么这么火？我认为就是所谓的SOA，而这种SOA，更多是很无奈的遗留系统的集成：我有跑了几十年的C、COBOL系统，现在想让它对其它新系统提供服务，不用WS，还有更好的选择吗？WS这种东西在日本开始流行，因为日本的信息化比中国早不下20年，它们的应用集成需求非常大，而中国的企业信息化才开始几年，集成需求并不强烈。<br /><br />对于EAI，我认为JMS还不是主流，应该说是Message系统，如IBM的MQ，因为它是跨语言的。而且Message系统可以很好处理像事务这些关键的企业应用需求。<br />而REST在这个方面还不成熟，虽然有补偿事务。另外，REST也没有安全规范，而基于SOAP有WS-Security规范，虽然也是这三年的事情，也不是很成熟。当然，基于SOAP的WS的事务规范目前也只是draft阶段。<br />如果REST不能保证<strong>安全、事务</strong>这两个关键性需求，那么，我认为它就很难在企业应用领域推广，也许互联网应用还不错，如成功实施REST的Amazon、ebay。<br />而分布式，主要还是在企业应用。<br />REST，我认为更多是一种 <strong>naked </strong>HTML，专门供应用程序读取，而不是通过浏览器供人看的HTML。<br /><br />我们往往以做互联网应用的视角来思考企业应用，大家现在去看专门做企业应用领域的TIBCO（<a href="http://www.tibco.com" target="_blank">http://www.tibco.com</a>：BPM、SOA）、IBM、BEA的产品家族核心就知道了。<br /><br />据一些大公司推测，未来最有市场前景的几个领域，应该是EAI、电子商务、ERP。
          <br/>
          <span style="color:red;">
            <a href="http://zwchen.javaeye.com/blog/83960#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 28 May 2007 20:37:03 +0800</pubDate>
        <link>http://zwchen.javaeye.com/blog/83960</link>
        <guid>http://zwchen.javaeye.com/blog/83960</guid>
      </item>
      <item>
        <title>也说说项目成败、企业信息化</title>
        <author>zwchen</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zwchen.javaeye.com">zwchen</a>&nbsp;
          链接：<a href="http://zwchen.javaeye.com/blog/81109" style="color:red;">http://zwchen.javaeye.com/blog/81109</a>&nbsp;
          发表时间: 2007年05月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          这篇文章是我对nbsp同学一篇帖子的回复：<a href="http://www.javaeye.com/topic/74996" target="_blank">http://www.javaeye.com/topic/74996</a><br />想想，也可以说我对企业信息化的一点粗浅看法，就做成blog备份吧。<br /><br /><br />lz总结的两点我很认同：<br />软件的价值 -->客户依赖程度<br />软件的质量 -->客户的满意度<br />仔细想想，这样可以解释为什么上面nbsp同学说的一个汽车销售项目5w－2w－1800，到最后的6000RMB搞定。为什么那么大的差别了：客户是否对这个软件很依赖。<br /><br />另外，nbsp同学的经历，也是中国企业信息化很普遍的一个现象：企业自己也不知道这个软件干嘛用，能够产生多大的价值，只是因为别人有，我也应该有：我这么大的一个公司，还没有个网站，太落后了吧。如果以这个想法出发，那么客户做个网站的目的，只是为了一个形象工程，或是广告效应。这样的网站在中国不计其数啦，1800一个，想接私活不？<br />中国的客户很不成熟，所以做为一个专业的软件的公司，一定要给客户好好“上上课”，让它们理解什么是“信息化”，可以给它们带来哗哗的钞票。<br /><br />我们公司前段时间接到一个项目，项目经理找我咨询，寻求解决方案，客户是大连中铁快运，上市公司。<br />客户要求：<br />我们企业需要信息化，需要有一个内部邮件系统，供公司员工使用。<br />需要一个BBS，大家可以在上面交流。<br />需要一个网站，有公司介绍、招聘、新闻，后台维护....<br />另外，它们只愿意花10W以下，一个月搞定。<br /><br />它们的需求写得很模糊，一页纸。你知道我们一开始怎么考虑吗？<br />怎么将三种产品集成啊？BBS＋Email＋WebSite集成不容易，虽然我们做个类似的，但SSO和跨语言很难搞定。<br />是自己开发吗？时间和开发量太大。<br /><br />经过和客户一番沟通后，我们才明白客户的真实需求：就是最常见的嘛，不痛不痒就行了。<br />最后我们怎么做呢？<br /><br />一个人负责找个开源的php CMS，简单改改，在上面建网站，做页面。另外，找个开源的php BBS，也随便改改。<br />找公司IT服务部一个会Qmail的同事，两天时间配了一个邮件服务器。<br />找了个美工，临时帮点忙，美化美化CMS、BBS。<br />另外找了个Java开发人员，做个招聘什么的频道，就是增删改差，可别按51job那样设计，找死。<br /><br />就这样，一个月下来，搞定！ 客户验收、系统上线时他们还挺满意：哇，这么漂亮，功能这么多！ 他们才不关心什么系统集成，单点登录。其实，这样对于它们并不重要。<br /><br />想想，要是我们给它们单独开发网站，恐怕这个就不只10w，另外跨语言系统集成多难啊，项目肯定是延期、超预算。<br />因为这些系统也不涉及它们核心业务，我们不是给他们做物流系统，所以他们也不想投入那么多。<br /><br />像以上那种客户，很值得培养。我们公司做这个项目，也并不想赚什么钱，因为公司几百w，千万的项目多的是。为什么还要这么做呢？因为这种客户端潜力很大，将来很可能搞到百万级以上的单子。公司后续的工作，就是给他们灌输什么信息化之路啊。他们老总一想：哦，真是这么回事，一开窍，呵呵....<br /><br />像上面的客户，你说他不成熟吧，也是。但是你应该看到，这种不成熟，就是市场啊。<br />当然，遇到不成熟客户，我们也吃过亏。<br />前年，一个1000多w的项目。当时单子拿下来后，我们打算用RUP的流程，迭代开发，并且项目组几十人都接受半个多月的RUP和OOA/D培训。<br />但是，客户就是希望看到阶段性的成果。最后是：上交需求说明书，付款20％，上交设计书20％.......。瀑布开发，风险之大，可想而知。项目做到最后，真是不堪设想啊，部分子系统重做。我认为需求不明确是罪魁祸首，但又怪谁呢？客户也是很强势的。<br /><br />另外，在项目投标过程中，好几家大公司竞标，xxx公司出700w，yyy公司出1200w，zzz公司1200万，我们公司最高：1500w，中标了。why？我们外围人士分析，至少有一个原因：客户的钱是国家拨款，钱多，当然啦，客户相关人士油水多。<br />我看了几家的投标书，xxx公司的最实在，1000多页，两本印刷装订书，说得头头是道，可惜客户不买单。后来我阅读那些投标书，确实是东软的我评价最高。<br /><br />还有很多感想呢，这次就说到这儿吧。
          <br/>
          <span style="color:red;">
            <a href="http://zwchen.javaeye.com/blog/81109#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 19 May 2007 15:25:18 +0800</pubDate>
        <link>http://zwchen.javaeye.com/blog/81109</link>
        <guid>http://zwchen.javaeye.com/blog/81109</guid>
      </item>
      <item>
        <title>读HSQLDB的源码想到的</title>
        <author>zwchen</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zwchen.javaeye.com">zwchen</a>&nbsp;
          链接：<a href="http://zwchen.javaeye.com/blog/80532" style="color:red;">http://zwchen.javaeye.com/blog/80532</a>&nbsp;
          发表时间: 2007年05月17日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          昨天在论坛看到一篇讨论嵌入式数据库HSQLDB(<a href="http://www.javaeye.com/topic/79802" target="_blank">http://www.javaeye.com/topic/79802</a>)的帖子，想到自己曾经读过部分它的源码，有一种对某些技术豁然开朗的感觉。所以，也希望和朋友们一起分享，大家有什么好的感受，不如也分享一下吧。下面是我对那个帖子的冗余回复，我觉得有必要专门发一篇帖子重复一下：<br /><br />说点题外话，建议大家读读HSQLDB的源码，特别是jdbc driver（<strong>org/hsqldb/jdbc包</strong>）那部分，写得清晰易懂。读了它的部分源码，我自认为对下面一些问题理解深入了：<br />1、JDBC规范和JDBC实现的关系：怎么自己去设计一个规范，一种架构？我是否自己可以为某种数据设计jdbc driver，如何设计？想想php里面各数据库的函数库各自为政对程序移植性的影响，就知道jdbc规范有多么重要了。<br /><br />2、JDBC协议：JDBC是基于socket之上的，数据包格式（<strong>org.hsqldb.Result</strong>)（mysql数据包格式公开了）？那么JMS数据包呢？其实，这也可以延伸到分布式协议的设计原理，如RMI、SOAP。其实，这些数据包格式和JSON、YAML这些message格式没有本质的区别，只不过应用范围不一样。任何分布式协议，肯定有一种message格式。<br /><br />3、JDBC over HTTP：这样我们对RMI over IIOP, soap over HTTP, http tunnel原理有更深入的理解。<br /><br />4、什么是long connection（jdbc的socket)，什么是short connection（http)，具体怎么实现？<br />3和4这些在HSQLDB的<strong>org.hsqldb.HTTPClientConnection</strong>类里有实现。<br /><br />5、Java客户端和服务器端的通讯实现：jdbc driver就可以认为是一个java客户端类库。那么JMS client呢？还有，像mysql有各种语言的driver，原理是什么。<br /><br />6、sql这种command、描述型语言究竟在数据库里面是个什么地位：sql是怎么传入jdbc driver，最终和database交互的？我们是否可以设计出另外一种command，形成一种行业标准，它在服务器和客户端怎么实现的。<br /><br />以上我的表达可能有些晦涩，我只想表达一点：大家有兴趣就多读读经典的源码，扩展一下自己的设计思路。可能很多人象我一样，总有忙不完的项目，那么抽几个小时就够了，不必深入。<br />有很多技术我们理解总是很模糊，当你深入到内部，忽然发现原来就这么回事。我们总觉得IoC很神秘，其实最简单的IoC容器，也许一个HashMap就够了。
          <br/>
          <span style="color:red;">
            <a href="http://zwchen.javaeye.com/blog/80532#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 17 May 2007 10:36:53 +0800</pubDate>
        <link>http://zwchen.javaeye.com/blog/80532</link>
        <guid>http://zwchen.javaeye.com/blog/80532</guid>
      </item>
      <item>
        <title>IBM WebSphere Application Server 诊断和调优(一)</title>
        <author>zwchen</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zwchen.javaeye.com">zwchen</a>&nbsp;
          链接：<a href="http://zwchen.javaeye.com/blog/74737" style="color:red;">http://zwchen.javaeye.com/blog/74737</a>&nbsp;
          发表时间: 2007年04月25日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          近段时间，我们项目中用到的WebSphere应用服务器(WAS)，但在客户的production环境下极不稳定，经常宕机。给客户造成非常不好的影响，同时，也给项目组很大压力。为此，我们花了近一个月时间对其诊断，现在基本上稳定了，需要继续观察一段时间。现在我主要将工作做一个阶段性的总结。<br />我们的产品环境是：WAS6.0＋DB2 8.1＋AIX5.3＋RS/6000。在该产品环境下，出现的问题非常多，现象如下：<br />WAS经常不稳定、宕机几乎一天一次，经常报告OutOfMemory(内存泄漏吗？NO)。<br />DB2连接数过大，有时把DB2撑死，有时也把AIX撑死。<br />AIX虚拟内存报错、分页报错、IO也报错、还有很多其它莫名奇妙的错。<br /><br />总是，每次问题发生的现象和理论上的总是不一致，导致我们不知道从何入手，也无从检测自己的优化参数。咨询过多次IBM技术支持，只解决了某些局部问题。<br />虽然问题依然存在，但我想，解决问题的思路、特别是理论基础，还是有一些规律和原则。<br /><br />对于WAS这块，我近段时间的主要时间集中在以下几个方面(时间顺序)：<br />1、Java性能监测工具：Jprofiler，也用到Jprobe。后来发现Jprofiler在AIX下几乎不可用。<br />2、IBM Java虚拟机和WAS技术细节，特别是IBM JVM的GC原理，我发现它和sun、bea的差别很大。<br />3、IBM的heap分析器Heap Analyzer、GCCollector。这两个事后监测工具非常实用，特别是我们的产品运行环境，非测试环境。<br />4、某些Application的怀疑和诊断。<br />5、AIX诊断，我几乎没有这个能力，只能常规监测一下，需另请高人。<br /><br />我打算将本文分成以下几个部分总结：<br />JVM原理、IBM JVM的GC策略和调优。<br />Jprofiler和IBM工具的实际体会<br />WAS的诊断体会和AIX调优<br /><br />下面开始主题吧，可能比较零碎，另外，开始的理论篇基本上看书都可以，我只是总结一下，再添加一些自己的理解。<br /><br />以下是我参考的最重要的两本电子书和一些网站：<br />《Inside Java Vrtual Machine》:半部分有约四章我认为非常棒，其它章节可能意义不大。<br />《The Java Virtual Machine Specification, 2nd》：前半部分有两三章很不错，不过可以对照上一本书看。<br />sun的hotspot虚拟机技术：<a href="http://java.sun.com/javase/technologies/hotspot/ " target="_blank">http://java.sun.com/javase/technologies/hotspot/ </a><br />BEA的JRockit虚拟机技术：<a href="http://edocs.bea.com/jrockit/geninfo/genintro/index.html " target="_blank">http://edocs.bea.com/jrockit/geninfo/genintro/index.html </a>JVM技术文档入口，虚拟机理论，内存泄漏诊断等的索引页。<br />IBM诊断资料：<a href="http://www-128.ibm.com/developerworks