发布新日志

  • 东风日产200万辉煌 浓情九月难忘师恩

    2010-09-12 16:50:55

      


    20109月初,中国汽车行业诞生了一个新的纪录,东风日产用短短的87个月成功跻身“200万辆俱乐部”。为了庆祝东风日产销量突破200万,跻身汽车行业“新贵”,值此教师节来临之际,东风日产南昌洪城专营店(东维汽车)将在910日至915日期间开展东风日产教师节“零距离购车”活动,届时与广大老师们共渡第26个教师节。

    200万辆——新的起点 从零开始

    2003年成立到第200万辆整车下线,东风日产走过了一条光荣但并非平坦的企业成长之路。高质量、重内涵的增长模式让东风日产实现了“做强做大”,“做强”是指不断提升经营质量、构建领先行业的综合竞争优势,“做大”成就了东风日产的发展速度和规模。

    基于对市场的敏锐判断和对消费者的深刻洞察,东风日产在各个细分市场都布下了重要的“棋子”,“梦八”组合覆盖了轿车、MPVSUVCROSS-OVER等领域,而且在每一个细分市场都是主流甚至领军车型。2009年东风日产旗下四款主力车型:天籁、轩逸、骐达颐达和骊威的月销量全部破万,创造了汽车企业从紧凑型车到中高级车全系进入“万辆俱乐部”的奇迹。

    相比其他车企的一“车”独秀,东风日产是国内为数不多的全车型覆盖厂商,它的全面开花让业界为之振奋:“一款产品成功,不足为奇。但款款皆被市场肯定,那就不得不对这个企业刮目相看。”同时随着市场的扩大、用户的成长,荣膺“2010下半年中国最受关注新车”的玛驰,是东风日产进军紧凑型家轿的首款力作。在绿色生活方式日益得到社会认可的背景下,它的导入为年轻一代消费者提供了全新的选择。

    浓情九月,致礼恩师

    九月终于如期而至,九月是金色的季节,是收获的季节,是回报的季节……老师,是这个季节的主题。 岁月如歌,师恩难忘。我们东风日产里的每一位员工同仁都有自己的恩师,正是恩师的教诲,才奠定了我们东风日产每个人发展成长的基石,为我们的东风日产这个年轻的团队注入了新鲜的血液。有了新鲜血液的注入,让我们东风日产人有无限的激情和战斗力,是我们在历时短短的7年之内跨越成就辉煌200万,创造了汽车史上的奇迹。值教师节来临之际,东风日产洪城专营店全体同仁在此对恩师们深深的说一句:亲爱的老师们!您们辛苦了,祝您们教师节快乐!

     中国有句古话,十年树木,百年树人,东风日产南昌洪城专营店(东维汽车)为谢师恩,于910日至915日特别推出“感恩园丁,倾情献礼”活动,把真情奉献给教师,凭教师证来店购车即可享受“尊师”优惠政策。详情致电南昌洪城专营店(东维汽车)热线:0791-3721088,恭候恩师您们的到来!

  • 曲建菲:农村文化建设的未来

    2009-11-13 12:04:09

     

        这两天看了看新闻出版总署的农民书屋政策,突然想起来两件事情。前一阵我刚看到一个电视连续剧,也只是瞟了一眼。那个画面是一个女村长,为了得到先进村的牌子,赶紧安排人弄了一个所谓的“文化馆”,其实就是一个十来平米的小屋子,放点书架和桌子,就算完事了,图书是县里边派发的。还一件事是我以前一直想的,加强文化交流,不仅是二三线城市,还有就是占中国主体的农民朋友们,尤其是山里的孩子,这是我一直的理想,真是希望能够帮助他们,改变他们的未来,提高中国总体文化素质。别的不多说了,政策非常好,惠及广大农民群众,推动农村公共文化服务体系建设,当我看到推荐书籍的列表,心里由生的感到欣喜。

        推荐书目分六大类,分别为政经类(328种)、科技类(850种)、生活类(531种)、文化类(1299种)、少儿类(557种)、其他(35种),可以说书籍的种类基本涵盖了生活学习的方方面面,从书籍种类的比列也可以看出,主要是为了加强农民技能建设和文化素质建设,还有就是提高祖国下一代的少儿教育。下面我分别谈一下个人看法:

        少儿教育

        推荐书目我大致看了一遍,还是不错的,符合少儿年龄层的发展需求,对少儿身心发展起到积极的推动作用。目前少儿读物普遍存在的现象是成人化严重,大部分书籍出现重复化,成人化,说教化的三化趋势,迫使青少年远离图书,更为严重的是,这种现象让孩子过于早熟,失去了童真,失去了了解真善美的途径。国家现在很多研究机构和专家提出分级化阅读,我觉得就非常好,加强图书出版机构的监督,对内容进行严格审核和分级,避免出现不良内容,并实现按照不同年龄段的智力和心理发育程度进行科学划分,完成一个从小到大、由浅入深的递进过程。

        看到很多农村的青少年的照片,真实的揭露了农民现状,孩子们非常可怜,我们需要给他们更多的关注和爱,让他们健康成长,做好国家坚实可靠的后备力量。

        技能教育

        科技类图书我也大致的看了一遍,符合农村发展现状,可以有效满足农村建设需求,包括致富思想,农业技能,生活技能,轻工业技能等,覆盖了农村生产的方方面面,可以有效提高生产率,为创收提供有效保证。以前看一个电视连续剧,描述的是一堆农民壮汉进城打工,家里的上上下下就指望着他们寄回的那点生活费,如果没有男人在外面打工,家里连锅都开不了,这个场景着实可怜。可往往造物弄人,这些男人全都迫不得已返乡了,为什么?归根结底就是没文化,没技能。社会发展的步伐,早已使大都市实现了现代化,原有的低效率劳动力全部被淘汰回家,而农村建设又没有跟上,致使这么多人只能挨饿受苦,不要说让他们自己创业,自己致富了,就连基本的操作一下机器,似乎都是天方夜谈。

        加强农村技能建设,是提高全民生活质量的有效保证,是提高中国GDP的直接前提,让我们对农村多一份关注,加强一份爱,拉动占全国人口60%的农民朋友,是使国家繁荣富强的推动力。

        文化教育

        文化,毋庸置疑,承载着中国五千年的历史,传承着中华民族的优良传统,提高农民的文化建设,可以有效改善中国全民素质,向着和谐社会的目标更进一步。我们可以看到很多农民在大都市乞讨,也可以看到很多人做着违法的行当,更有很多女性做着出卖自己肉体,更出卖自己灵魂的行为。这些都无不体现加强文化建设的重要性。我们都说看一个人美不美帅不帅,并不是外表,而是内涵,当一个人素质提高,其魅力自然流露其间,相由心生,也有这样一番含义。

        关注农村文化建设,是增强中国在世界地位的有效途径。只有全民素质提高了,中国才能发展的更为强大。

     

       让我们关注农村建设,关注农民文化建设,对给他们一份爱,多给他们一份帮助。在此感谢那些西部建设的人们,感谢那些下乡育人的教师,感谢那些为农村改革的领导们,你们辛苦了。

  • 曲建菲:重新的自我审视

    2009-11-01 18:16:30

       《史玉柱创业思维》,看到书名以为是介绍创业过程的书,相当于个人传记什么的,抑或是创业家的思维定式,就好像《富爸爸》系列图书里面提到的富人思想。不过看完后,没有找到当初我想要了解的团队建设过程和创业初期的细节,不过这些不能否定这本书的魅力,其他的内容深深的影响了我,使我又开始了新一轮的自我审视。 


        去年以前,我一直觉得我擅长的有三个方面,管理,营销,交际。就管理而言,经过这两年的学习和实践,发现了很多的不足,我需要不断完善自己的方法论,观察人和事,在跌碰中不断成长;营销是我一直认为的优势,从大学的创业到后来的多次实战,都有很多值得回忆的东西,层出不穷的想法和方式,以及观察市场的角度,让我肯定自己的价值;交际是我以前比较自豪的,但现在我一点不这么想了,因为我发现我认识的人涉及领域很窄,这就是我现在唯一的瓶颈。 


        看完这本书后,我感触很深,因为我更进一步的认识到了自己的不足。首先,就管理而言,我还没有管理好目前的团队,虽然思想统一,并且做事高效,但是我发现我没有把人情和管理分开,这样会直接导致未来队伍松散,我自身就没有严格要求自己,若团队不断壮大,将很难行动统一。还有就是,若创办家企业,这个特定时期的管理和范围要远远比现在考虑的多,并且我喜欢每一个人都很强,这就需要领导人有足够魅力来吸引每一位成员,现在我还没有驾驭这样团队的能力,就像史玉柱在困难时期,还有那么多的人不离不弃,大家信服他,当然想柳传志这类人都是一样。再说营销,这本书介绍史玉柱的营销思维很多,我全都表示赞同,甚至有点志同道合的感觉,书中史玉柱做试点的做法,让我想起来大学时在市场上各个攻破客户时的回忆,书中的广告策略,也让我想起来我写的商业策划书中的内容,不过史玉柱不愧是史玉柱,还有很多想法让我学习了,并经过分析和成本核算,完全可以用到我的项目中。其中软文编写的注意点和策略,还有农村包围城市,这些让我佩服,也是我第一次发现毛泽东思想的永垂不朽。最后说交际,我现在也是在不断学习,不断积累的过程,人脉确实非常重要,记得有句话说的好,成功=50%的勤奋+50%的人脉,直到现在我才感到另一番意义,这次是从事业来看成功,以前只是单纯的从职场角度理解的。 


        现在我要做的,就是一步一个脚印,创业的每一步都做到实处,真正的做起来,将每一次碰到的问题进行总结,从实践中不断学习。并且拓展人脉,让自己和成功再进一步。

  • 流沙帮自己达成梦想

    2009-10-29 22:46:35

    我自己的优势是什么?

    我自己的劣势是什么?

    我自己喜欢的是什么?

    我自己厌烦的是什么?

    这些问题的答案是需要丰富的阅历才可以不断完善的。

     

        现在,这些问题的答案我似乎已经得出了结论,但是随着答案的浮出水面,我自身的烦躁感却逐渐增加。优势中有了更多的欠缺,原本肯定的东西,现在也出现了很多可以指出的问题。劣势让我看到了自身存在的严重不足,而这些往往却决定着一个人的成败。喜欢的东西已经渐渐远去,剩下的就是无限的烦恼。厌烦的东西无情的折磨着我,让我变得麻木。

        眼下脑子里很多事情,每个都会让我激动不已,每个又都会让我痛苦至极。这感觉,就好像你想往前走,但你每走一步,似乎都在往后跑,可是你又不能停,因为你就这么点时间,你站着就永远到不了前面想去的地方,你就只能死在这个地方。怎么办,没办法,走吧,越走越往后退,心里这叫一个急!不过现在认清了自己,再回过头来看看,似乎发现了前进的方法。我自己的优势是还年轻,还有那么一点点脑子,我的劣势是什么,没有认清环境,没有找到可以帮我前进的工具。我喜欢的是什么,就是到我想去的那个地方,我厌烦的是什么,厌烦我自己连跑都不会跑,就瞎跑,逞什么强。

        再拿上面这个感觉来说,眼前是什么环境,是一片流沙,你越想往上爬,越挣扎,你越往下沉,不过我这里的流沙是往后流的,我越往前走,我就飞似的往后退,这就是我所处的环境。好在有点脑子,看看我生长在什么地方,这个地方叫地球,是圆的,往后怎么了,能不能到,能到。再分析分析怎么跑,我往前走,就等于往后跑,往后走,就等于往后飞奔,这是流沙,就只能这么跑。最后看看需要什么辅助设施,我得弄点工具,弄辆车,帮我加快点速度,不行,一辆怎么够,地球多大,得多来几辆,这样时间才短嘛。OK,这些都想好了,得做吧,先转身,然后找车,找了一辆,再找N辆,找够了为止,他们是帮我的,没坏处,但是还不能找破车,还不够我拖车的呢,费油。OK,加满油,把车都连起来,走人。剩下的就是自己考验自己耐心的时刻,终于有一天我会到达这个目的地的。

        说了这么多,想说什么呢,我现在需要一步一个脚印的,把自己需要补充的都补充完善,做完一个事情,再做另一个,这样我才能稳步向前,谁都不可能一口气吃成一个胖子。不断的成熟,不断的学习,才能让自己挑战一个又一个的困难,战胜自己的同时,也让自己离目标越来越近。

  • 另一番意味——团队建设

    2009-10-18 21:05:29

        商学院,名副其实,不过又和富爸爸的核心理念——拥有自己的事业有点相违背。传统意义上的商学院有三个方向,分别为创业,管理和投资。而这本书我认为更偏重于管理。
        书中一直在提网络营销这个概念,我想和我们中国市场的网络营销,有着截然不同的概念和意义。富爸爸系列图书中,如果说《富爸爸,穷爸爸》教会了人们要注重理财和现金流的话,那么《富爸爸,商学院》我觉得更偏重于团队氛围建设。为什么这么说呢?因为读完全书,我收获的不是认识到网络营销的魅力,不是创业的逐步推进,而是网络营销公司的团队力量和价值。
        相同价值观的团队,人脉拓展,推销能力,失败换就的成功,领导技巧的方法,互助和分享,等等。这些都无不体现在团队建设的方方面面,帮助我们更好的建设和管理团队,帮助每一个成员不断成长。让他们感受到团队内所有人都是志趣相投的朋友;不要害怕失败,因为你会因此而学习到更多;如何让大家在互助和分享的氛围中,不断提高自己;告诉我们怎样推销自己的想法,可以更好的让团队行动一致,达成目标;还有让我们明白怎样才能进行有效的领导。
  • 测试中测试工具的地位

    2009-08-10 20:00:32

    一年前写的文章了,突然发现,感觉还挺有意思。

    本文出自曲建菲(pupu840323)的51testing博客,转载请注明出处及链接http://www.51testing.com/?uid/137809            

               测试工具介绍
        随着软件测试的地位逐步提高,测试的重要性逐步显现,测试工具的应用已经成为了普遍的趋势。目前用于测试的工具已经比较多了,这些测试工具一般可分为白盒测试工具、黑盒测试工具、性能测试工具,另外还有用于测试管理(测试流程管理、缺陷跟踪管理、测试用例管理)的工具。

        总的来说,测试工具的应用可以提高测试的质量、测试的效率。但是在选择和使用测试工具的时候,我们也应该看到,在测试过程中,并不是所有的测试工具都适合我们使用,同时,有了测试工具、会使用测试工具并不等于测试工具真正能在测试中发挥作用。
    1、应用测试工具的目的
        1)提高测试质量
        2)减少测试过程中的重复劳动
        3)实现测试自动化

    2、测试工具的分类
       1)白盒测试工具
           ①静态测试工具(检查代码质量)
           Telelogic公司的Logiscope软件、PR公司的PRQA软件、Jprobe
           ②动态测试工具(监测系统数据)
            Compuware公司的DevPartner软件、Rational公司的Purify系列
       2)黑盒测试工具
           ①功能测试工具(减少重复工作)
           Rational公司的TeamTestRobotCompuware公司的QACenter
          ②性能测试工具(系统性能瓶颈)
           Radview公司的WebLoadMicrosoft公司的WebStress
       3)其他测试工具
        包括数据库测试工具,应用性能优化工具等
       4)测试管理工具(测试过程管理)
       Rational公司的Test ManagerCompureware公司的TrackRecord

    3、测试工具的选择
        现在市面上的测试工具功能上大体相同,只是一些规则不太相同,我们需要选择的工具在报表上一定需要表现完整清楚,在集成方面需要能够和我们的开发工具以及其他测试良好的集成在一起,有良好的兼容性。随着我们测试工作的不断完善,测试工具也需要循序渐进的进行引入,不可盲目引入。

    4、测试工具在公司中的应用
        我们公司现在引导的是人人皆测试的思想,由此而产生了轮岗制度,但是光是有测试的思想还是远远不够的,就我们的开发人员来说,引入白盒测试工具,提高代码质量也是需要考虑的方面。由于我们接触的项目比较少,就现在的项目BI来说,测试工具QTP并不是很适合使用,但是通过合理的对脚本进行修改,再加上对工具进行设置和下载相应插件,对BI的测试还是可以顺利进行的。正确的使用测试软件也是我们测试人员需要考虑的问题,当然针对这个项目,我们使用人工手动进行测试,效率还是比较高的。
        测试工具的培训工作也是相当重要的,只有人人有思想还要人人皆上手,从基本概念到基本使用,从提出问题到交流探讨,这是一个长期的过程,也希望经过轮岗制度能够做到这样的目的。

  • 2008年终总结

    2009-06-16 21:41:45

    本文出自曲建菲(pupu840323)的新浪博客,转载请注明出处及链接http://blog.sina.com.cn/qujf

    一年一年的,感觉时间过的飞快。回顾2008年,收获颇丰,成就感油然而生,可是这些却又都劲不起推敲,细细品来也觉得索然无味。

    生活与工作,难舍难分的两个兄弟,每个人的喜好各有偏重,如何换位思考,将他们的性质互换,我始终没有明白,因为换位思考是一种技能,更是一种天性,我可以换位思考去想人,想事,但始终无法去思考自我。是时候停下脚步来整理一下思绪,否则会被抑郁与空虚吞噬。

    悲喜交加的一年,黑白无常的一年,2008注定是一个不平凡的岁月,灾难迭起,奥运成功,金融危机。同样我也在经历着风风雨雨,从上半年的堕落,到下半年的奋斗,变化最大的是态度。面对生活环境转变的态度,面对工作内容不同的态度,面对机遇与挑战的态度,面对失败与失意的态度,面对情感的纷繁复杂……,思绪万千的我慢慢地喜欢在寂静的黑夜中享受一个人的宁静,很多事情也渐渐的明白了。

    一、突破自我

    生活会让人快乐,也会让人疲惫,这要看自己用何种眼光来审视这个世界,心理学做过很多实验,当人用消极被动眼光来看时,自我会产生极大的压力,当人用积极主动眼光来看时,会激发自我潜力,产生意想不到的效果。然而我总是悲观的看待任何事物,不希望步入“自欺欺人”的行列,但往往却是孤独地行走在宽阔大道上,自卑、压力使我前进的更加迟缓。

    回顾一年的历程,我不知道做了什么,也许我用电脑打出的文字可以覆盖整个地球表面,也许有多个深夜中的通宵奋战,也许提出了很多的测试思想,但终归那些都是工作职责范围内的,也是作为一个测试人员应该做的内容,而这一年中所做的不完美与不深入,是我的遗憾。

    不过相比一年前,又怎能想象得到今天我所收获的呢。看看自己制定的PBC,半年的时间已经基本完成,当时的情景犹如今日:这么多东西,我就得用一年的时间,没法再多了,我想稳扎稳打。这是当时和经理说的话,意思大概就是如此,没想到半年里自己已经成长了,这算不算是一种突破呢。

    种子破土而出,蝴蝶破茧而出,他们都是在不知不觉中完成了蜕变,他们在默默无闻中成长,经历了不为人知的艰辛,然而面对他们的是美好的明天与自我的成长。再看我自己,是否就像他们一样呢?这是否就是突破自我呢。

    二、沟通协作

    人与人之间的关系真的很微妙,从幼儿园到大学,人们的情感时时刻刻在变化,合作的关系也有着不同层面的表现。步入社会后,所有的一切都成为了复杂的集合体,只有细细品味其中,才能了解各种滋味。

    网,一张残缺的网无法发挥他自身的作用,顶多成为摆设,一张结实有力的网,则会成为我们有利的陌生工具,施展他的价值。这些网是如何编制在一起,并且如此坚固耐用呢?我想是因为编织的人对网的结构非常清楚,并且了解每个网点间的编织顺序和方法。了解和熟悉就成为了首要前提。

    团队和网是相同的,他们都有着共同的特点,如何将团队建设得如网一般结实有力,就需要如编织人一样了解网的结构,了解每一个网点的情况,他们之间的连接则是相互间的沟通协作。

    当我身处其中时,我默默的观察着身边所发生的一切以及自身所做的努力,在沟通协作的过程中,让我看到了社会学的人类行为,也看到了很多心理学的表现,了解了各种不同性格的人,以及他们的沟通方式。环境、角色、阶层等等因素都会对我们的交流产生影响,我做到了吗?这需要通过时间和结果来体现。

    三、稳定心态

    24个年头,经历过很多,每一页都有不同的色彩,所以一直认为自己很成熟。彩信报里有句话说:男人最怕别人说自己小,女人最怕别人说自己老。很赞同,用在自己身上尤其如此,可是最近发现,自己从来没有成熟过。

    一年的波澜起伏,造成很多磕磕碰碰,我一直在寻找一次惨痛的失败与教训,想激起我走向成功的契机,然而这本身就衬托出我幼稚的本性。无论情感还是工作,总是在支配我的心态变化,让自己成为了不稳定的个体,也正是如此,造成了我的失败与失意。

    理性与感性,我各执一方,理性带给我生活的反思与总结,感性带给我生活的随意与快乐。让他们各负其责,会使生活与工作更加愉悦,但如果将他们本末倒置或者偏颇一方,则会产生抑郁,有可能是对精神的渴求,也有可能是对生活的不满。自小羡慕生活潇洒的人,感觉他们将事物处理的错落有致,条理分明,相比之下,自己则逊色颇多。

    失衡的心态会让人做出错误的抉择,可能无法挽回,也有可能只有最后一次。它在无形中引导你,再让你追悔莫及,一切都在不经意间发生了,理性与感性被放到了本不该放置的地方。当将他们互换位置,眼前似乎增添了一副眼镜,将所有的问题都看得透彻清晰,再也不会掉进伪装的陷阱。

     

    2008就这样过去了,2009又会什么样呢。

    期待明天,期待自己

    期待清晨的一缕彩虹高挂

    期待破茧而出的彩蝶飞翔

  • 安全测试版资料汇总(转载)

    2009-04-07 17:22:36

    本文出自ttkk的个人空间,转载请注明出处http://www.51testing.com/?247622
     
    1.Rational AppScan Enterprise Edition 7.7.654安装程序下载
    http://bbs.51testing.com/thread-137577-1-1.html

    2.安全性测试方法
    http://bbs.51testing.com/thread-63812-1-1.html

    3.系统安全性测试总结
    http://bbs.51testing.com/thread-120076-1-1.html

    4.入侵的艺术(安全测试
    http://bbs.51testing.com/thread-71327-1-1.html

    5.使用APPSCAN进行安全性检测总结
    http://bbs.51testing.com/thread-85970-1-1.html

    6.安全技术培训资料---安全标准
    http://bbs.51testing.com/thread-122993-1-1.html

    7.分享信息安全人员培训资料--安全技术
    http://bbs.51testing.com/thread-126102-1-1.html

    8.安全技术培训资料---系统网络与信息安全
    http://bbs.51testing.com/thread-123005-1-2.html

    9.安全性测试ppt,自己写的
    http://bbs.51testing.com/thread-113815-1-1.html

    10.WEB安全测试通常要考虑的测试点
    http://bbs.51testing.com/thread-112894-1-1.html

    11.SQL Server 系统检查流程
    http://bbs.51testing.com/thread-124025-1-2.html

    12.Oracle 安全检查流程
    http://bbs.51testing.com/thread-124024-1-2.html

    13.IIS系统检测流程
    http://bbs.51testing.com/thread-124023-1-2.html

    14.CISCO检查流程
    http://bbs.51testing.com/thread-124022-1-2.html

    15.应用系统安全检查流程
    http://bbs.51testing.com/thread-124021-1-2.html

    16.安全技术培训资料---cisco安全管理实例
    http://bbs.51testing.com/thread-123062-1-2.html

    17安全技术培训资料---系统网络与信息安全
    http://bbs.51testing.com/thread-123005-1-2.html

    18.举例说明对数据库SQL注入
    http://bbs.51testing.com/thread-131908-1-2.html

    19.应用系统安全测试内容及方法
    http://bbs.51testing.com/thread-110657-1-6.html

    20.安全技术培训资料---unix系统安全管理
    http://bbs.51testing.com/thread-123024-1-5.html

    21.分享信息安全人员培训资料--安全技术
    http://bbs.51testing.com/thread-126102-1-1.html

    22.网络安全培训资料
    http://bbs.51testing.com/thread-85970-1-1.html
  • 理解WAS 6.1 的类加载(4)(转载)

    2009-04-07 16:25:42

    12.5.2 步骤 2:添加一个EJB模块和工具JAR

    下面,往应用程序中添加一个EJB,它也依赖VersionChecker JAR文件。在此,在EAR的根目录添加一个VersionCheckerV2.jar 文件。在这个JAR文件中的VersionChecker  类返回了Version 2.0。为了保证扩展类加载中的工具JAR可用,在EJB模块的manifest文件中添加一个引用,如例12-8:

    例12-8 更新EJB模块的 MANIFEST.MF 文件

    Manifest-Version: 1.0

    Class-Path: VersionCheckerV2.jar

    现在的结果是:有一个Web模块,在它的WEB-INF/classes 目录下面有一个servlet,在WEB-INF/lib 目录下面有VersionCheckerV1.jar 文件。还有一个EJB模块引用了EAR根目录下面的VersionCheckerV2.jar 工具JAR。你期望Web模块装入VersionChecker 类文件的版本是什么?是WEB-INF/lib 下的Version 1.0 还是工具JAR下面的Version 2.0?测试结果如例12-9:

    例12-9 类加载 例2

    VersionChecker called from Servlet

    VersionChecker is v2.0.

    Loaded bycom.ibm.ws.classloader.CompoundClassLoader@26282628

    Local ClassPath:

    C:\WebSphere\AppServer\profiles\AppSrv02\installedApps\kcgg1d8Node02Cel

    l\ClassloaderExample.ear\ClassloaderExampleEJB.jar;C:\WebSphere\AppServ

    er\profiles\AppSrv02\installedApps\kcgg1d8Node02Cell\ClassloaderExample

    .ear\VersionCheckerV2.jar

    Delegation Mode: PARENT_FIRST

    VersionChecker called from EJB

    VersionChecker is v2.0.

    Loaded bycom.ibm.ws.classloader.CompoundClassLoader@26282628

    Local ClassPath:

    C:\WebSphere\AppServer\profiles\AppSrv02\installedApps\kcgg1d8Node02Cel l\ClassloaderExample.ear\ClassloaderExampleEJB.jar;C:\WebSphere\AppServ

    er\profiles\AppSrv02\installedApps\kcgg1d8Node02Cell\ClassloaderExample

    .ear\VersionCheckerV2.jar

    Delegation Mode: PARENT_FIRST

    正如所看到的,当同时调用EJB模块和Web模块,VersionChecker 是 Version 2.0 。当然,原因是:WAR类加载器将请求委托给了父类加载器而不是他自己,所以工具JAR就被同一个类加载器加载,而无需考虑请求是来自于servlet还是EJB。

    12.5.3 步骤 3:改变WAR类加载的委托模式

    现在是否希望Web模块使用WEB-INF/lib 目录下面的VersionCheckerV1.jar 文件?为了这个目的,需要先将类加载委托模式从parent first 改为parent last。

    设置委托模式为PARENT_LAST,使用如下步骤:

    1. 在向导栏选择Enterprise Applications;

    2. 选择ClassloaderExample 应用程序;

    3. 在模块部分选择Manage modules ;

    4. 选择ClassloaderExampleWeb 模块;

    5. 将类加载顺序修改成应用程序类加载优先(PARENT_LAST)。记住,这个条目应该称为WAR类加载优先,参见 “类加载/委托模式”;

    6. 单击 OK.

    7. 保存配置

    8. 重新启动应用程序。

    WEB-INF/lib 下的VersionCheckerV1 返回version of 1.0。可以在例12-10中看到:

    例12-10 类加载 例3

    VersionChecker called from Servlet

    VersionChecker is v1.0.

    Loaded bycom.ibm.ws.classloader.CompoundClassLoader@4d404d40

    Local ClassPath:

    C:\WebSphere\AppServer\profiles\AppSrv02\installedApps\kcgg1d8Node02Cel

    l\ClassloaderExample.ear\ClassloaderExampleWeb.war\WEB-INF\classes;C:\W

    ebSphere\AppServer\profiles\AppSrv02\installedApps\kcgg1d8Node02Cell\Cl

    assloaderExample.ear\ClassloaderExampleWeb.war\WEB-INF\lib\VersionCheck

    erV1.jar;C:\WebSphere\AppServer\profiles\AppSrv02\installedApps\kcgg1d8

    Node02Cell\ClassloaderExample.ear\ClassloaderExampleWeb.war

    Delegation Mode: PARENT_LAST

    VersionChecker called from EJB

    VersionChecker is v2.0.

    Loaded bycom.ibm.ws.classloader.CompoundClassLoader@37f437f4

    Local ClassPath:

    C:\WebSphere\AppServer\profiles\AppSrv02\installedApps\kcgg1d8Node02Cel

    l\ClassloaderExample.ear\ClassloaderExampleEJB.jar;C:\WebSphere\AppServ

    er\profiles\AppSrv02\installedApps \kcgg1d8Node02Cell\ClassloaderExample

    .ear\VersionCheckerV2.jar

    Delegation Mode: PARENT_FIRST

    如果你使用类加载器的搜索功能,搜索*VersionChecker*,会得到图12-9:

    图12-9 类加载查看器搜索功能

    例12-11 显示源代码

    例12-11 类加载查看器搜索功能

    WAS Module Compound Class Loader (WAR class loader):

    file: / C: / WebSphere / AppServer / profiles / AppSrv02 /

    installedApps / kcgg1d8Node02Cell / ClassloaderExample.ear /

    ClassloaderExampleWeb.war / WEB-INF / lib / VersionCheckerV1.jar

    WAS Module Jar Class Loader (Application class loader):

    file: / C: / WebSphere / AppServer / profiles / AppSrv02 /

    installedApps / kcgg1d8Node02Cell / ClassloaderExample.ear /

    VersionCheckerV2.jar

    12.5.4 步骤 4:使用共享库共享工具JAR

    在此之前,只有一个应用程序使用VersionCheckerV2.jar 文件。是否希望多个应用程序能够共享它?当然,你可以在每个EAR文件中把这个文件打包进去。但是如果需要修改这个工具JAR,那需要重新部署所有的应用程序。为了避免这个麻烦,你可以使用共享库全局共享这个JAR文件。

    共享库可以定义在单元、节点、应用程序服务器集群。一旦你定义了共享库,必须将它跟应用程序服务器的类加载器或者单独的Web模块关联起来。根据共享库指派的目的地不同,WebSphere会使用匹配的类加载器加载共享库。

    只要愿意,可以定义多个共享库。也可以为应用程序、Web模块或者应用程序服务器指派多个共享库。

    在应用程序级别使用共享库
    定义一个名为VersionCheckerV2_SharedLib 的共享库,并把它跟ClassloaderTest 应用程序关联起来,步骤如下:

    1.     在管理控制台,选择Environment → Shared Libraries;

    2.     选择共享库的作用域,比如单元,单击New;

    3.     如图12-10:

    图 12-10 共享库配置

    – Name: 输入VersionCheckerV2_SharedLib;

    – Class path: 输入类路径中的条目,每个条目之间用回车隔开。如果提供绝对路径,建议是用WebSphere环境变量,比如 %FRAMEWORK_JARS%/VersionCheckerV2.jar ,确定你已经定义了一个和共享库相同作用域的变量。

    – Native library path: 输入JNI代码使用的DLLs 和.so 文件列表。

    4.     单击 OK;

    5.     选择 Applications → Enterprise Applications;

    6.     选择应用程序 ClassloadersExample ;

    7.     在引用选项,选择 Shared library references ;

    8.     在应用程序列选择 ClassloaderExample ;

    9.     单击 Reference shared libraries;

    10.  选择 VersionCheckerV2_SharedLib ,单击 >> 按钮将选中的移动到 Selected 列,如下图12-11:

    图12-11 指定一个共享库

     

    11.  单击OK ;

    12.  ClassloaderExample 应用程序共享库配置窗口如下图12-12:

    图12-12 将共享库指派给应用程序 ClassloaderExample


     

    13.  单击OK ,保存配置。

    如果我们现在从EAR文件的根目录将VersionCheckerV2.jar删除,在EJB模块的manifest文件中也把引用删除,重新启动应用服务器,看到例12-12的结果。记住,Web模块的类加载顺序依然是应用程序类加载优先(PARENT_LAST)。

    例12-12 类加载 例4

    VersionChecker called from Servlet

    VersionChecker is v1.0.

    Loaded bycom.ibm.ws.classloader.CompoundClassLoader@2e602e60

    Local ClassPath:

    C:\WebSphere\AppServer\profiles\AppSrv02\installedApps\kcgg1d8Node02Cel

    l\ClassloaderExample.ear\ClassloaderExampleWeb.war\WEB-INF\classes;C:\W

    ebSphere\AppServer\profiles\AppSrv02\installedApps\kcgg1d8Node02Cell\Cl

    assloaderExample.ear\ClassloaderExampleWeb.war\WEB-INF\lib\VersionCheck

    erV1.jar;C:\WebSphere\AppServer\profiles\AppSrv02\installedApps\kcgg1d8

    Node02Cell\ClassloaderExample.ear\ClassloaderExampleWeb.war

    Delegation Mode: PARENT_LAST

    VersionChecker called from EJB

    VersionChecker is v2.0.

    Loaded bycom.ibm.ws.classloader.CompoundClassLoader@19141914

    Local ClassPath:

    C:\WebSphere\AppServer\profiles\AppSrv02\installedApps\kcgg1d8Node02Cel

    l\ClassloaderExample.ear\ClassloaderExampleEJB.jar;C:\henrik\VersionChe

    ckerV2.jar

    Delegation Mode: PARENT_FIRST

    正如预料的,由于Web模块的委托模式,当servlet 需要VersionChecker 类,VersionCheckerV1.jar 文件被加载。当EJB需要VersionChecker 的类的时候,就会从指向C:\henrik\VersionCheckerV2.jar 的共享库中加载它。如果你希望Web模块也使用共享库,只需要将类加载顺序恢复成缺省值,Web模块的类加载是父类加载优先。

    在应用程序服务器级别使用共享库
    共享库也可以跟应用程序服务器关联起来。在这个服务器上的部署的所有应用程序都能够看到共享库的代码列表。要把共享库跟应用程序服务器关联起来,首先要为应用程序服务器创建一个附加的类加载器,步骤如下:

    1.     选择应用程序服务器;

    2.     在应用程序基础结构部分,展开 Java and Process Management,选择 Class loader;

    3.     选择New,为这个类加载器选择类加载顺序,父类加载优先 (PARENT_FIRST) 或者应用程序类加载优先 (PARENT_LAST),单击 Apply;

    4.     单击刚刚创建的类加载器;

    5.     单击 Shared library references;

    6.     单击 Add,选择希望跟应用程序服务器关联的库。重复选择操作,将多个库跟这个类加载器关联。比如选择 VersionCheckerV2_SharedLib 条目;

    7.     单击 OK;

    8.     保存配置;

    9.     重新启动应用程序服务器,修改才会生效。

    将VersionCheckerV2  共享库跟应用程序服务器关联起来,就得到例12-13的结果。

    例12-13 类加载 例5

    VersionChecker called from Servlet

    VersionChecker is v1.0.

    Loaded bycom.ibm.ws.classloader.CompoundClassLoader@40c240c2

    Local ClassPath:

    C:\WebSphere\AppServer\profiles\AppSrv02\installedApps\kcgg1d8Node02Cel

    l\ClassloaderExample.ear\ClassloaderExampleWeb.war\WEB-INF\classes;C:\W

    ebSphere\AppServer\profiles\AppSrv02\installedApps\kcgg1d8Node02Cell\Cl

    assloaderExample.ear\ClassloaderExampleWeb.war\WEB-INF\lib\VersionCheck

    erV1.jar;C:\WebSphere\AppServer\profiles\AppSrv02\installedApps\kcgg1d8

    Node02Cell\ClassloaderExample.ear\ClassloaderExampleWeb.war

    VersionChecker called from EJB

    VersionChecker is v2.0.

    Loaded bycom.ibm.ws.classloader.ExtJarClassLoader@7dee7dee

    Local ClassPath: C:\henrik\VersionCheckerV2.jar

    Delegation Mode: PARENT_FIRST

    我们定义的新的名为 ExtJarClassLoader  类加载器,在EJB模块请求时,它装入VersionCheckerV2.jar 文件。由于委托模式,WAR类加载器继续装入自己的version。

    12.6 类加载器问题诊断

        JVM 5.0提供了一些配置,可以让我们查看详细的类装入,比如JVM 参数 -verbose:dynload、-Dibm.cl.verbose=<name>。

        在实际开发过程中,如果使用不当,会出现很多类加载相关的问题。当遇到类加载问题时,可以查看WAS的相关日志,在日志中出现如下异常,可以认为是类加载器出现了问题:

    ClassCastException

    ClassNotFoundException

    NoClassDefFoundError

    NoSuchMethodError

    IllegalArgumentException

    UnsatisfiedLinkError

    VerifyError

    关于问题诊断,将在下一篇文章《WAS 6.1 类加载问题诊断》详细阐述。

    总结

    本文针对WAS6.1版本,详细介绍了类加载的概念以及如何客户化,并通过几个例子向大家讲述了影响类加载的选项的使用。虽然WAS 6.1 允许根据需要修改类加载策略,比如将父类优先改成应用程序优先,但是不推荐这么使用。笔者曾经就遇到因为修改策略,导致应用程序无法启动。原因是WAS中的组件和应用程序使用的某些类是一致的,加载策略选择不正确,就会导致类加载错误。

    参考资料

    1.WebSphere Application Server V6.1: System Management and Configuration

    http://www.redbooks.ibm.com/abstracts/sg247304.html?Open

    2.WebSphere Application Server V6.1: Classloader Problem Determination

    http://www.redbooks.ibm.com/abstracts/redp4307.html?Open

    3.类装入问题解密,第 1 部分: 类装入和调试工具介绍

    http://www.ibm.com/developerworks/cn/java/j-dclp1/

    4.类装入问题解密,第 2 部分: 基本的类装入异常

    http://www.ibm.com/developerworks/cn/java/j-dclp2.html

    5.类装入问题解密,第 3 部分: 处理更少见的类装入问题

    http://www.ibm.com/developerworks/cn/java/j-dclp3/

    6.类装入问题解密,第 4 部分: 死锁和约束

    http://www.ibm.com/developerworks/cn/java/j-dclp4/

    7.J2EE 类装入揭密

    http://www.ibm.com/developerworks/cn/websphere/library/techarticles/0112_deboer/deboer.html

    8.WAS 6.1 信息中心

    http://publib.boulder.ibm.com/infocenter/wasinfo/v6r1/index.jsp 

    关于作者

    胡伟红,西安交通大学硕士,目前就职于IBM 软件部。主要负责 WebShpere软件产品的技术支持。可通过huweih@cn.ibm.com与她联系。

  • 理解WAS 6.1 的类加载(3)(转载)

    2009-04-07 16:17:29

    12.3.1 类加载策略

    对于系统中的每个应用程序服务器,类加载策略可以设置成 Single 或者Multiple。当应用程序类加载策略设置成 Single,单一的应用程序类加载器可以加载应用程序服务器(JVM)中的所有 EJB、工具JARs 和共享库。如果WAR类加载策略设置成Single类加载(或者Application),这个应用程序中的Web模块也会被这个single类加载器加载。

    当应用程序服务器类加载策略被设置成 Multiple,缺省值,每个应用程序会使用自己的类加载器加载EJB、工具JAR 和共享库。依赖于WAR类加载器加载策略是设置成应用程序中每个WAR文件使用自己的类加载器(或者称为Module),还是设置成Single 类加载(或者称为 Application),Web模块能够或者不能使用自己的类加载器。

    下面用一个例子说明。我们有两个应用程序,程序1和程序2,它们运行在同一个应用程序服务器上。每个应用程序有一个EJB模块,一个工具JAR和两个Web模块。如果应用程序服务器自己的类加载策略设置成缺省值 Multiple ,所有Web模块的类加载策略也设置成缺省值,即应用程序中的WAR文件都有自己的类加载器,如下图12-3:

    图12-3 类加载器策略:例一

    每一个应用程序被完全的分开,每个应用程序当中的Web模块也被完全的分开。WebSphere缺省的类加载策略就是应用程序和模块都是完全隔离的。

    如果我们现在把WAR2-2 模块的类加载策略修改成 Single,就会变成下图12-4:

    图12-4 类加载策略:例二

    Web 模块 WAR2-2 由程序2的类加载器加载,Util2.jar 中的类能够看到WAR2-2 的 /WEB-INF/classes 和/WEB-INF/lib 目录下的类。

    在上一个例子中,如果我们把应用服务器的类加载策略从Multiple改成Single,把WAR2-1模块的类加载策略从Module改成Single,结果就变成了下面的内容12-5:

        图12-5 类加载策略:例三

    现在只剩下一个应用程序类加载器加载程序1和程序2的。Util1.jar 中的类能够看到EJB2.jar、Util2.jar、WAR2-1.war 和WAR2-2.war 的类。然而,应用程序类加载器仍然看不到WAR1-1 和WAR1-2 的类,因为类加载器只能向上查看类而不能向下查看类。

    12.3.2 类加载/委托模式

    WebSphere 的应用程序类加载器和WAR类加载器都有一个称为类加载顺序的设置。这个设置决定了是否遵循正常的Java的类加载委托机制(见Java类加载器介绍)还是覆盖它。

    类加载模式有两个可能的选项:

    l         父类优先

    l         应用程序优先

    在WebSphere 的早期版本中,这个设置称为 PARENT_FIRST 和 PARENT_LAST。缺省类加载模式是父类优先(PARENT_FIRST)。这个设置要求类加载器在加载自己类路径中的类之前先加载父类。这是标准Java类加载器的缺省策略。

    如果类加载策略设置成应用程序优先(PARENT_LAST),类加载器就会在加载父类之前,先把自己的类路径中的类加载进来。这个策略允许应用程序类加载器覆盖和提供已经在父加载器中存在的自己版本的类。

    注意: 在这一点上,管理控制台有点模糊。在Web模块的配置界面,类加载顺序有两个选项:父类加载器优先和应用程序类加载器优先。然而,根据上下文,这里的“应用程序类加载器”其实指的是WAR类加载器,所以应用程序类加载器优先其实指的是WAR类加载器优先。

    假如你有一个应用程序,类似于之前例子中的程序1,EJB模块和两个Web模块都使用log4j 生成日志。假定每一个模块把自己唯一的log4j.properties 文件打包进模块文件中。在EAR文件中,你只需要把log4j配置成工具JAR就可以了。然而,如果这样做,你可能会奇怪所有的模块都会看到这个jar文件,包括Web模块,尽管log4j.properties 文件是EJB模块加载的。

    原因是, 当Web模块初始化log4j包时,应用程序类加载器加载了log4j的类。Log4j 被配置成工具JAR。Log4j 会在自己类路径下查找log4j.properties 这个文件,在EJB模块中发现了它。

    如果EJB模块不使用log4j记录日志,EJB模块中也不包含log4j.properties  文件, log4j 不会在任何的Web模块中找到log4j.properties 这个文件。原因是类加载器只能够向上查找类,而不能向下。

    要解决这个问题,可以这么做:

    1.     单独创建一个文件,比如,Resource.jar,把它配置成工具JAR,把所有的log4j.properties 都移到这个文件里面,但是要保证文件名唯一(比如 war1-1_log4j.properties、war1-2_log4j.properties 和 ejb1_log4j.properties)。当从每个模块中初始化 log4j 的时候,告诉它为模块装入正确的配置文件,而不是都使用缺省(log4j.properties)。在原始位置(/WEB-INF/classes)存放Web模块的log4j.properties,把log4j.jar 添加到所有的Web 模块(/WEB-INF/lib)下,设置Web模块的类加载模式为应用程序类加载优先(PARENT_LAST)。当从Web模块中初始化log4j,模块自己装入log4j.jar,log4j  在自己的本地类路径下找到log4j.properties 。当EJB模块初始化log4j的时候,从应用程序类加载中加载,在相同的类路径下找到EJB1.jar中的log4j.properties.

    2.     如果可能,把所有的log4j.properties 文件合并成一个,放在应用程序类加载器中,比如放在Resource.jar  文件中。

     12.3.3 共享库

    共享库是多个应用可以公用的文件。典型的例子是框架的使用,比如Apache Struts 或者log4j。可以让共享库指向一个JAR集合,把这个JAR文件跟应用程序、Web模块或者应用程序服务器类加载关联起来。当你有多个不同版本的相同框架,你希望跟不同的应用程序关联,这个时候就能够使用共享库。共享库通过控制台进行定义。定义项包括一个象征性的名字,Java类路径和装入JNI库的native 路径。可以在单元、节点、服务器或者集群中定义共享库。但是,简单的定义一个库不会装入这个库的。必须把这个库跟一个应用程序、Web模块或者应用程序服务器的类加载器关联起来,这个共享库才能够被加载。如果共享库跟应用程序服务器类加载器关联起来,服务器上的所有应用程序都能够使用这个库。

    注意: 如果已经把一个共享库跟应用程序关联起来,就不要把同一个共享库跟这个应用程序服务器关联起来。

    可以通过如下两种方法关联共享库:

    1.     可以使用管理控制台。在企业应用程序界面,引用选项可以关联到共享苦,创建共享库。

    2.     可以使用应用程序的 manifest 文件和共享库。库的依赖会在应用程序 manifest 文件中指明,在扩展列表中罗列出库的扩展名。

    使用管理控制台,将共享库跟应用程序服务器的类加载器关联起来。这个设置能够在服务器基础架构中找到。展开Java和进程管理,选择 Class loader ,单击 New 按钮,定义一个新的类加载。一旦定义了一个新的类加载器,你可以修改它,同时使用共享库引用连接,可以把这个共享库跟新建的类加载器关联起来。

    请查看“步骤4:: 使用共享库共享工具JAR”

    12.4 类加载查看器

    V6.0.2新特性: WebSphere Application Server V6.0.2 引入了一个新的工具,类加载查看器。一旦激活,这个工具能够帮助你诊断类加载问题,显示不同类加载器,设置以及每个的类加载情况。

    如果类加载查看器服务不可用,类加载查看器只能显示类加载器的层次结构以及他们的路径,而不是每个类加载器的具体类加载情况。也就是类加载查看器的查询功能缺省是不可用。

    要启动类加载查看器服务,执行如下:Servers → Application Servers → <server name> ,选择Additional Properties  链接下的Class Loader Viewer Service,接着选择 Enable service at server startup 。完成这个设置,需要重新启动应用服务器才能够生效。

    在下一节,我们会给出一个例子,说明不同类加载器如何工作以及使用类加载查看器记录不同的结果。

    12.5 通过案例学习类加载

    我们已经介绍了多个影响类加载的选项。这个部分,会举一个例子来说明这些。

    创建一个简单的应用程序,有一个servlet,一个EJB。它们都调用一个类,VersionChecker ,见例12-4。这个类可以打印出哪一个类加载器加载这个类。VersionChecker 类还有一个内部值, 显示正在使用的是哪个版本的类。这个会在后面用到,用来描述同一个工具JAR的不同版本的使用情况。

    例12-4 VersionChecker 类源代码

    package com.itso.classloaders;

    public class VersionChecker {

    static final public String classVersion = "v1.0";

    public String getInfo() {

    return ("VersionChecker is " + classVersion +

    ". Loaded by " + this.getClass().getClassLoader());

    }

    }

    一旦装入,可以通过如下链接访问应用程序:http://localhost:9080/ClassloaderExampleWeb/ExampleServlet。它启动了调用了VersionChecker 的ExampleServlet,会显示出例12-5中的信息:

    例12-5  调用 ExampleServlet

    VersionChecker is v1.0.

    Loaded bycom.ibm.ws.classloader.CompoundClassLoader@71827182

    Local ClassPath:

    C:\WebSphere\AppServer\profiles\AppSrv02\installedApps\kcgg1d8Node02Cel

    l\ClassloaderExample.ear\ClassloaderExampleWeb.war\WEB-INF\classes;C:\W

    ebSphere\AppServer\profiles\AppSrv02\installedApps\kcgg1d8Node02Cell\Cl

    assloaderExample.ear\ClassloaderExampleWeb.war\WEB-INF\lib\VersionCheck

    erV1.jar;C:\WebSphere\AppServer\profiles\AppSrv02\installedApps\kcgg1d8

    Node02Cell\ClassloaderExample.ear\ClassloaderExampleWeb.war

    Delegation Mode: PARENT_FIRST

    VersionCheckerV1.jar 文件包含了 VersionChecker 类文件,它返回版本数是1.0。如下测试,如果没有特别指出,类加载策略和加载模式都使用缺省值。换句话说,应用程序有一个类加载器,WAR文件有一个。两个的委托模式都设置成了父加载器优先(PARENT_FIRST )。我们假定应用程序已经加载到了一个名为AppSrv02的应用服务器上了。

    12.5.1 步骤 1:简单的Web模块打包

    假定这种情况:我们的工具类只被一个servlet调用。把VersionCheckerV1.jar 文件放在WEB-INF/lib 目录下面。 对于这样的配置,运行应用程序时,出现例12-6中的内容。

    例12-6 类加载 例1

    VersionChecker called from Servlet

    VersionChecker is v1.0.

    Loaded bycom.ibm.ws.classloader.CompoundClassLoader@71827182

    Local ClassPath:

    C:\WebSphere\AppServer\profiles\AppSrv02\installedApps\kcgg1d8Node02Cel

    l\ClassloaderExample.ear\ClassloaderExampleWeb.war\WEB-INF\classes;C:\W

    ebSphere\AppServer\profiles\AppSrv02\installedApps\kcgg1d8Node02Cell\Cl

    assloaderExample.ear\ClassloaderExampleWeb.war\WEB-INF\lib\VersionCheck

    erV1.jar;C:\WebSphere\AppServer\profiles\AppSrv02\installedApps\kcgg1d8

    Node02Cell\ClassloaderExample.ear\ClassloaderExampleWeb.war

    Delegation Mode: PARENT_FIRST

    从上述跟踪信息中,可以得到:

    1.类加载器的类型是:

    com.ibm.ws.classloader.CompoundClassLoader.

    2.查找类的顺序是:

    ClassloaderExampleWeb.war\WEB-INF\classes

    ClassloaderExampleWeb.war\WEB-INF\lib\VersionCheckerV1.jar

    ClassloaderExampleWeb.war

    WEB-INF/classes 目录包含了没有打包的资源(比如servlet 类、Java类和配置文件),但是WEB-INF/lib 目录下就包含了打包好的JAR文件。你可以选择将Java代码打包到JAR文件中,将他们放到库目录下面或者可以未打包直接放在类路径下面。他们会在同一个类路径下面。由于我们的示例应用程序都是使用Application Server Toolkit开发和导出的,servlet直接就在类目录下面,在导出应用程序的时候,toolkit不会把Java类打包成一个JAR文件。WAR文件的根是下一个能够存放代码或者配置文件的地方,但是不建议这么用,因为这个目录对于Web服务器是文档根的目录,所以这个目录下的任何内容都能够通过浏览器直接访问。根据J2EE的规范,WEB-INF是受保护的,这就是为什么classes和lib目录都在WEB-INF目录下。

    在应用程序启动的时候,类加载器的类路径是动态构建的,我们可以使用类加载查看器显示类加载。在管理员控制台上,选择Troubleshooting → Class Loader Viewer,展开server1 → Applications → ClassloaderExample → Web modules,单击 ClassloaderExampleWeb.war,就会看到如下图12-6:

    图 12-6 类加载器显示应用程序树

    展开Web模块时,类加载查看器显示了从JDK扩展类加载器到JDK应用程序类加载器再到WAR类加载器的层次结构,称为混合类加载器,参见12-7:

    图12-7 类加载查看器显示类加载层次

    如果你展开WAS模块的类路径----混合类加载器,可以看到跟VersionChecker打印出来同样的内容。见12-7。

    例12-7 类加载查看器显示的WAR类加载器的类路径

    file:/C:/WebSphere/AppServer/profiles/AppSrv02/installedApps/kcgg1d8Nod

    e02Cell/ClassloaderExample.ear/ClassloaderExampleWeb.war/WEB-INF/classe

    s

    file:/C:/WebSphere/AppServer/profiles/AppSrv02/installedApps/kcgg1d8Nod

    e02Cell/ClassloaderExample.ear/ClassloaderExampleWeb.war/WEB-INF/lib/Ve

    rsionCheckerV1.jar

    file:/C:/WebSphere/AppServer/profiles/AppSrv02/installedApps/kcgg1d8Nod

    e02Cell/ClassloaderExample.ear/ClassloaderExampleWeb.war

    类加载查看器会提供一个表,显示所有类加载器和每个加载器加载的类。同时这个表也显示出了委托模式:True 表示类的加载方式是父加载优先(PARENT_FIRST);false 表示类的加载方式是应用程序类加载优先 (PARENT_LAST),或者在只有一个Web模块的情况下是WAR类加载,见图12-8:

    图12-8 类加载查看器结果表

    正如所看到的,WAR类加载器已经装入示例中的servlet 和VersionChecker 类。类加载查看器还提供了查询功能:可以查找类、JAR文件、目录等等。如果你不知道类加载器加载了哪个类,这个功能就很有用。查询功能是大小写敏感但是允许使用通配符,比如使用*VersionChecker* 查询 VersionChecker  类。

  • 理解WAS 6.1 的类加载(2)(转载)

    2009-04-07 15:40:29

    本文转载自胡伟红博客,转载请注明出处http://www.webspherechina.net/?1790/

    12.2 概览Websphere 类加载器

    注意:每一个JVM都有自己的类加载器。在WebSphere 环境中会有多个应用程序服务器(JVM),也就是说JVM的类加载器是分开的,尽管它们运行在同一个物理机器上。

    还需要注意的是:Java虚拟机(JVM) 使用的扩展和应用程序类加载器,你能够看到WebSphere 运行环境也使用名为扩展和应用程序类加载器,尽管它们的名字有些一致,但它们和JVM使用的是不一样的。

    WebSphere 提供了几个客户化委托类加载器,如下图12-2:

    图12-2 Webspere 类加载器层次图


    最顶端的方框表示Java类加载器(引导、扩展和应用程序)。WebSphere 在这里加载它自己的引导类加载器和初始化WebSphere扩展类加载器。

    12.2.1 WebSphere 扩展类加载器

    V6.1新特性: WebSphere 扩展类加载器是WebSphere 加载自己的地方。在WebSphere之前的版本,运行环境被单一的类加载器加载。然而,从WAS6.1开始,WebSphere 被打包成若干OSGi(Open Services Gateway Initiative) 包。每一个OSGi 包都由自己的类加载器加载。OSGi 类加载器的网络通过OSGi网关类加载器跟扩展类加载器和类加载器层次结构中的其余部分相连。

        不管WebSphere装入自己类的方式如何改变,应用程序也不会有改变。还是同样的可见性、同样的类加载选择。

    V6.1新特性:WAS之前的版本中,WebSphere运行时类文件保存在<was_home>目录下的classes、lib、lib\ext和installedChannels 目录下。由于OSGi包,这些目录都不存在了,运行时类文件会存放在<was_home>\plugins 目录下。

    扩展类加载器的类路径是由ws.ext.dirs 系统属性指定,也就是setupCmdLine 脚本文件中指定的WAS_EXT_DIRS环境变量设置。ws.ext.dirs 的缺省值如例12-3:

    例12-3 we.ext.dirs 的缺省值

    SET

    WAS_EXT_DIRS=%JAVA_HOME%\lib;%WAS_HOME%\classes;%WAS_HOME%\lib;%WAS_HOME%\insta

    lledChannels;%WAS_HOME%\lib\ext;%WAS_HOME%\web\help;%ITP_LOC%\plugins\com.ibm.e

    tools.ejbdeploy\runtime

    ws.ext.dirs 环境变量中列出的每个路径都会被添加到WebSphere扩展类加载器的类路径中,并且该目录中的每个JAR文件和ZIP文件都会被添加到类路径中。

    正如所看到的,尽管在<was_home>目录中不再有classes、lib、lib\ext 和installedChannels文件夹,但是setupCmdLine 脚本文件会把它们添加到扩展类路径中。这就意味着,如果之前你已经把自己的JAR文件添加到<was_home>\lib 目录下,你可以创建这个目录并且把JAR文件添加进去,它们依然会被扩展类加载器加载。然而,不推荐这么做,在安装过程中还是正确的迁移比较好。

    另一方面,如果你已经开发了Java应用程序,它依赖之前在<was_home>\lib 目录下的WebSphere JAR文件,你需要让你的程序保留兼容性。WAS 6.1 针对这样的应用程序提供了两种瘦客户端库:管理客户端库和Web 服务客户端库。可以在<was_home>\runtimes 目录下面找到这两个客户端库:

    _ com.ibm.ws.admin.client_6.1.0.jar

    _ com.ibm.ws.webservices.thinclient_6.1.0.jar

    这些库为应用程序提供了连接和与WebSphere一起工作的所有内容。

    缺省设置是Allow,意思是你的应用程序可以无限制的调用非公用的内部WebSphere 类。但是不推荐这么使用,在未来的版本这个功能可能会被限制。因此,作为管理员,如果应用程序还能正常运行,最好把这个设置改成Restrict。如果它们依赖非公用的WebSphere内部类,你就收到一个ClassNotFoundException,这样还得改成Allow。这样开发人员就需要对应用程序进行移植,以保证应用程序能够兼容未来的WAS版本。

    V6.1新特性:WAR 6.1 限制对WebSphere内部类的访问,这样你的程序才不会依赖那些未公开发布的WAS 的API。这个设置针对每个服务器(JVM),称为访问内部服务器类。

    12.2.2 应用程序和Web模块类加载器

    J2EE 应用程序包含五个主要元素:Web 模块,EJB 模块,应用程序客户端模块,资源适配器(RAR文件),工具JAR。工具JAR包含了EJB 和Servlet使用的代码。log4j  就是一个好的典型的工具框架的例子。EJB 模块、工具JAR、资源适配器文件和应用程序关联的共享库都会归结到同一个类加载器。这个类加载器称为应用程序类加载器。根据类加载器的规则,缺省情况下,多个应用程序(EAR)可以共享这个类加载器或者每一个应用程序都有对应的类加载器。

    缺省情况下,Web 模块使用它们自己的类加载器(WAR类加载器)加载WEB-INF/classes 和EB-INF/lib 目录下的内容。通过修改应用程序WAR类加载策略可以改变这个缺省情况。

    缺省情况,应用程序中每个WAR文件都有自己的类加载器(早期的版本,这个设置称为 Module)。如果WAR类加载策略设置成Single(早期的版本称为Application)类加载器,除了EJB、RAR、工具JAR以及共享库之外,Application类加载器还加载Web模块的内容。Application类加载器是WAR类加载器的父亲。Application类加载器和WAR类加载器都是可重装入的类加载器。一旦它们自动监测到程序代码改变了,就会重装入修改的类。我们可以在部署应用程序的时候改变这个行为。

    12.2.3 操纵JNI 代码

    因为JVM只有一个地址空间,每个地址空间中native代码只能装入一次,JVM规范要求在JVM中native代码只能被一个类加载器加载。

    例如,这将导致一个问题,如果你有一个包含两个Web模块的应用程序(EAR文件),两个Web模块都需要通过Java Native Interface(JNI)装入native 代码,那么只有第一个被加载的Web模块能够成功。

    为了解决这个问题,你可以把加载到类中的native 代码拆分成多个Java代码并且把它放在WebShpere应用程序类加载器(放在工具JAR)中。然而,如果要在同一个应用程序(JVM)中部署多个这样的应用程序(EAR文件),你需要把类文件放到WebSphere扩展类加载器上,取代每个JVM只能加载一次native代码。

    如果native 代码放在一个可加载的类加载器(比如应用程序类加载器或者WAR类加载器),有一点很重要:能够正确的卸载自己的native代码而Java代码能够重加载。WebSphere 无法控制native代码,如果native代码不能正确的卸载或者加载,应用程序可能失败。

        如果native 库依赖另一个,事情就会变得很复杂。关于native库的依赖关系,请查看信息中心。

    12.3 配置 WebSphere 类加载器

    在之前的内容中,我们了解了WebSphere 类加载器以及类加载器如何协同工作。这一部分我们会讨论如何修改WAS的配置来影响Websphere类加载的行为。

  • 理解WAS 6.1 的类加载(1)(转载)

    2009-04-07 15:28:48

    本文转载自胡伟红博客,转载请注明出处http://www.webspherechina.net/?1790/

     

    胡伟红

    2008年7月

    skill level:初级 

    abstract:本文截取IBM 红皮书《WebSphere Application Server V6.1:系统管理与配置》的第 12 章节内容,详细阐述了类加载器的基本概念和使用,以及如何客户化类加载器,通过例子阐述了影响类加载的选项的使用。 

    keywords:WebSphere Application Server ,类加载器  

    常常有客户询问我,WAS 中的类加载策略怎么理解。这不是一句话能够说清楚的。所以截取了IBM 红皮书《WebSphere Application Server V6.1:系统管理与配置》的第 12 章节,详细阐述了类加载器的基本概念和使用,以及如何客户化类加载器。

    理解Java以及Websphere的类加载策略对打包和部署J2EE程序至关重要。当启动应用程序时,如果类加载失败,就会出现类加载的异常,比如ClassNotFoundException。本文解释了类加载以及为了应用程序的需要如何客户化Websphere 类加载。

    后简称WebSphere Application Server V6.1 为WAS 6.1

    12.1 Java类加载器介绍

    类加载器负责把类加载到Java虚拟机(JVM)中。指定类的名称,类加载器就会定位这个类的定义,每一个Java类必须由类加载器加载。

    当启动JVM的时候,可以使用三个类加载器:引导(bootstrap)类加载器、扩展(extensions)类加载器、应用程序(application)类加载器。

    1.引导类加载器仅仅负责加载核心的Java库,比如位于<JAVA_HOME>/jre/lib 目录下的vm.jar,core.jar。这个类加载器,是JVM核心部分,是用native代码写成的。

    2.扩展类加载器负责加载扩展路径下的代码,一般位于<JAVA_HOME>/jre/lib/ext  或者通过java.ext.dirs 这个系统属性指定的路径下的代码。这个类加载器是由sun.misc.Launcher$ExtClassLoader 实现的。

    3.应用程序类加载器负责加载java.class.path(映射系统参数 CLASSPATH的值) 路径下面的代码,这个类加载器是由 sun.misc.Launcher$AppClassLoader 实现的。

    当处理类加载器时,父委托模式是一个需要理解的关键概念。它规定:类加载器在加载自己的类之前,可以委托先加载父类。父类加载器可以是客户化的类加载器或者引导类加载器。但是有一点很重要,类加载器只能委托自己的父类加载器,而不能是子类加载器(只能向上不能向下)。

    扩展类加载器是应用程序类加载器的父亲。类加载器的层次图见图12-1 。

    图12-1 类加载器层次图

    如果应用程序类加载器需要加载一个类,它首先委托扩展类加载器,扩展类加载器再委托引导类加载器。如果父类加载器不能加载类,子类加载器就回在自己的库中查找这个类。基于这个特性,类加载器只负责它的祖先无法加载的类。

    如果类加载器加载一个类,这个类不是在类加载器树上的叶子节点上,就会出现一些有趣的问题。比如例12-1,一个名为WhichClassLoader1 的类加载了一个名为WhichClassLoader2类,WhichClassLoader2又调用了名为WhichClassLoader3的类。

    例12-1 WhichClassLoader1 和 WhichClassLoader2 源代码

    public class WhichClassLoader1 {

    public static void main(String[] args) throws javax.naming.NamingException

    {

    // Get classpath values

    String bootClassPath = System.getProperty("sun.boot.class.path");

    String extClassPath = System.getProperty("java.ext.dirs");

    String appClassPath = System.getProperty("java.class.path");

    // Print them out

    System.out.println("Bootstrap classpath =" + bootClassPath + "\n");

    System.out.println("Extensions classpath =" + extClassPath + "\n");

    System.out.println("Application classpath=" + appClassPath + "\n");

    // Load classes

    Object bj = new Object();

    WhichClassLoader1 wcl1 = new WhichClassLoader1();

    WhichClassLoader2 wcl2 = new WhichClassLoader2();

    // Who loaded what?

    System.out.println("Object was loaded by "

    + obj.getClass().getClassLoader());

    System.out.println("WCL1 was loaded by "

    + wcl1.getClass().getClassLoader());

    System.out.println("WCL2 was loaded by "

    + wcl2.getClass().getClassLoader());

    wcl2.getTheClass();

    }

    }

    ======================================================================

    public class WhichClassLoader2 {

    // This method is invoked from WhichClassLoader1

    public void getTheClass() {

    WhichClassLoader3 wcl3 = new WhichClassLoader3();

    System.out.println("WCL3 was loaded by "

    + wcl3.getClass().getClassLoader());

    }

    }

    如果所有的WhichClassLoaderX 类都放在应用程序的类路径下,三个类就会被应用程序类加载器加载,这个例子就会运行正常。现在假定把WhichClassLoader2 类文件打包成JAR文件放在<JAVA_HOME>/jre/lib/ext 目录下,运行WhichClassLoader1,就会看到例12-2的输出:

    例12-2 NoClassDefFoundError  异常跟踪

    Bootstrap classpath

    =C:\WebSphere\AppServer\java\jre\lib\vm.jar;C:\WebSphere\AppServer\java\jre\lib

    \core.jar;C:\WebSphere\AppServer\java\jre\lib\charsets.jar;C:\WebSphere\AppServ

    er\java\jre\lib\graphics.jar;C:\WebSphere\AppServer\java\jre\lib\security.jar;C

    :\WebSphere\AppServer\java\jre\lib\ibmpkcs.jar;C:\WebSphere\AppServer\java\jre\

    lib\ibmorb.jar;C:\WebSphere\AppServer\java\jre\lib\ibmcfw.jar;C:\WebSphere\AppS

    erver\java\jre\lib\ibmorbapi.jar;C:\WebSphere\AppServer\java\jre\lib\ibmjcefw.j

    ar;C:\WebSphere\AppServer\java\jre\lib\ibmjgssprovider.jar;C:\WebSphere\AppServ

    er\java\jre\lib\ibmjsseprovider2.jar;C:\WebSphere\AppServer\java\jre\lib\ibmjaa

    slm.jar;C:\WebSphere\AppServer\java\jre\lib\ibmjaasactivelm.jar;C:\WebSphere\Ap

    pServer\java\jre\lib\ibmcertpathprovider.jar;C:\WebSphere\AppServer\java\jre\li

    b\server.jar;C:\WebSphere\AppServer\java\jre\lib\xml.jar

    Extensions classpath =C:\WebSphere\AppServer\java\jre\lib\ext

    Application classpath=.

    Exception in thread "main" java.lang.NoClassDefFoundError: WhichClassLoader3

    at java.lang.J9VMInternals.verifyImpl(Native Method)

    at java.lang.J9VMInternals.verify(J9VMInternals.java:59)

    at java.lang.J9VMInternals.initialize(J9VMInternals.java:120)

    at WhichClassLoader1.main(WhichClassLoader1.java:17)

    正如所看到的,由于WhichClassLoader3 在应用程序类路径下,程序失败,收到一个NoClassDefFoundError 的异常,这看起来有些奇怪。问题在于:它现在在一个错误的类路径下面。当WhichClassLoader2被扩展类加载器加载的时候,发生了什么呢?实际上,应用程序类加载器委托扩展类加载器加载WhichClassLoader2,扩展类加载器又委托引导类加载器。由于引导类加载器找不到这个类,类加载的控制就会返回给扩展类加载器。扩展类加载器在自己的路径下找到了这个类将它加载。现在,当一个类已经被类加载器加载后,这个类需要的任何其他的新类都必须用同一个类加载器加载他们(或者遵循父委托模式,由父类加载器加载)。所以当WhichClassLoader2 需要访问WhichClassLoader3 的时候,扩展类加载器就会获得这个请求去加载WhichClassLoader3,扩展类加载器先委托引导类加载器,但是引导类加载器找不到这个类,于是扩展类加载器便试图装入自身但是也找不到这个类,原因是WhichClassLoader3不在扩展类路径而是在应用程序类路径。由于扩展类加载器无法委托应用程序类加载器,所以就会出现NoClassDefFoundError 的异常。

     注意:开发者通常会使用如下语法通过类加载器机制加载属性文件:

    Properties p = new Properties();

    p.load(MyClass.class.getClassLoader().getResourceAsStream("myApp.properties"

    ));

    这个意思是:如果MyClass 由扩展类加载器加载,而 myApp.properties 文件只能应用程序类加载器看到,则装入属性文件就会失败。

  • 测试用例的意义以及适用性

    2009-03-03 16:56:10

    背景描述:对于稳定客户的项目类测试,经常会遇到需求三天一变,两天一变,由于时间周期不是太长,客户需求经常变动,导致BA/PM等都未能及时更新需求,从而给测试组的需求经常是非最新版本,且测试阶段的需求也经常有小变动,导致用例效果不大甚至失效.(可能是针对需求说明书失效,更多情况是针对实际需求-即系统实现方式失效).
    生命周期半年的项目需求是否有必要写用例?
     
    开门见山的说,我认为不需要写测试用例,但我们需要简化版的功能覆盖点。

    一、测试用例意义:
        测试用例主要是督促测试人员熟悉理解业务情况,辅助全面回归测试,梳理测试思路,测试用例的好坏,在交叉测试中尤为凸显。
        测试用例的引入,致使测试人员在测试之前就需要对业务很了解,知道如何着手测试,在这个过程中寻找模块间关联点,不断补充进测试用例。就好比油画,通过不断的渲染和填充,才能使我们发表一幅优秀的作品。他的作用就在于让我们深入透彻的了解系统架构和业务知识,以及数据关联性等。
        在回归测试以及交叉测试中,用例让我们可以很快速的想起测试思路和过程,帮助其他测试人员熟悉测试模块,检测其他人员的测试用例是否全面等。有很多时候,我们往往会突然冒出一些有亮点测试思路,但人又偏偏是记性差的生物,到后面也就忘记的干净,测试用例的记录,帮助我们将所有的测试思路和过程记录,辅助我们进行记忆。举个例子,一个人拿着模板来写字,您说能不容易吗。交叉测试中,别人对你的测试模块一无所知,再讲一遍,不仅自己感觉繁琐,也影响进度时间,而好的用例不需要讲解,就可以很好的引导测试人员进行测试工作。举个例子,盲人走路很困难,但有了导盲犬后,他们就可以非常方便的出行。
        通过上面这些,可以看出测试用例的重要性,可以说,测试用例是不可缺少的。

    二、测试用例适用性
        测试用例如果想实用,那麽他所带来的工作量就会非常大,我们需要很多的时间来完善和补充,所以如果项目变动很小,那麽测试用例将是长久性的保持效用。但如果项目变动大,则测试用例的维护成本将使测试质量明显下降。
        通过这些我们可以看出,测试用例在这种情况下又是不能引入的。

    三、解决方法
        为了解决测试用例的意义所带来的效益,测试用例适用性所带来的缺陷,我认为应该引入功能覆盖点来平衡这两方面因素。
        功能覆盖点是对所测试项目功能点的一个简要概括,编写功能覆盖点可以让我们去熟悉业务系统,平且将功能点,关联点等简单罗列,让我们纵观测试的广度和深度。在需求变动情况大的情况下,维护功能覆盖点的成本要远远小于测试用例,他所带来的效用是实效而灵活的。

        综上所述,测试用例在需求变动大的项目中,是不需要引入的,而应该引入更为实效的功能覆盖点,辅助测试工作的开展和考察。
  • 中国化发展

    2009-02-23 12:41:04

    本文出自曲建菲(pupu840323)的51testing测试网博客,转载请注明出处及链接http://www.51testing.com/?137809

         记得第一次面试时,面试题中有一道叫做《你知道的现有社区网站有哪些,以及你对他们的了解》。我当时就想,大学四年我白活了,连个社区网站都没上过,完全脱离时代了。我只能硬着头皮在卷子上一个命的拽,结果自然可以预料到。。。

         工作后,逐渐的开始上论坛遛弯,也慢慢的开始接触了社区网站。开心网自然算内地社区网站比较成功的一个,其主要是帮助寻找老朋友,在这里大家通过送礼物来表达对互相的关心和喜爱,通过小游戏来缓解日常工作学习中的压力。慢慢的开心成为了很多人日常生活中的一部分。

         最近发现了Facebook,其运作模式和开心非常类似,同样的还有校内网,当然我不知道哪个网站是首先提出这种商业运作模式,但是他们都同样的成功。他们的模式是相同的,但不同的是各自的“特色”。

         校内网

         以学生群体为主,帮助分布各地的大学生交流感情,探讨学习,大家最喜欢的就是小游戏以及分享帖子。我想导致这一现象的原因主要是这特定的客户群所致,年轻,有活力,充裕的时间以及求知的欲望。

         开心网

         以社会各类人群为主体,帮助寻找一生中所有的朋友,大家都知道很多人的朋友随着时间的流逝,逐渐失去了联系,但那份友情犹存。在这里大家最喜欢的就是投票以及游戏,生活工作的忙碌让他们在闲暇的时间可以通过小游戏进行放松,社会关系的复杂,人情的逐渐冷淡,让大家对别人的好奇或者内心话的发泄,导致投票的流行。

         Facebook

         以全球各类人群为主体,帮助寻找老朋友,聚会。他是我认为最为全面,成功被所有人群接受的社区网站,甚至连美国安全局,情报局都在这个网站开启了自己的网页,招聘社会人士。其最为成功的是group以及event,响应都非常热烈,其最根本原因就是中外区域文化不同导致。

         纵观以上网站,我们乍看上去他们的模式非常类似,但是都有各自的“特点”,主要原因是目标群体不同,以至于他们所引导的模式不同。这让我想起了外企,一个外国企业在中国本土开辟商机,如果套用原有模式运作,必然导致失败。就拿Facebook举例,若在中国想举办party,真是非常困难,多少的网络诈骗案,多少的勾心斗角,大家没有真实的一面,所有的人都被禁锢在自己的内心深处,至少这样可以免受伤害。由于这些社会现象和舆论,party这样的形式在中国就不会流行起来。那麽一个外企雇佣中国的CEO,或者中国的员工,进行本地化,中国化运作,自然不言而喻。就好比一个汽车企业,其主推车型在全球不同国家都进行了个性化改造,以适应各地不同用户的偏好,以此扩大市场占有率。再如延保公司在中国的发展,由于不同产品在各地的使用习惯不同,以及天气条件等特定原因,导致产品的使用寿命和其他国家有着明显的不同,这样的数据分析都是中国化后的产物,也是一些成功的延保公司业绩增长的首要前提。

         但是个性化定制带来的缺点就是成本和利益的平衡性,投入的成本是否可以将利润平均化。当然对于网站这样的低成本运作是不需要考虑这些的。我这里想说的是,汽车产业有全球化车型的概念,有效的解决了上面的问题,那麽网站的发展是否也可以进行全球化运作呢。Facebook就很好,支持多种语言是全球化的首要条件,我们看校内,开心都未曾做到这一点。全球化的网站所带来的直接经济效益是本地市场无法比拟的。

         中国化发展是所有外企一致的运作模式,加入世贸组织之后,外资的引入,中国企业受到了严重冲击,完善的管理制度,成熟的技术支撑,严格的成本把控等都是中国企业的致命伤。外企一般都是雇佣海归派的华人进行高层管理,他们虽然了解中国,但是仍然注入了西方的思想。中国企业有一个最有力的武器,就是中国深远文化的熏陶,我们了解国民需求。然而中国企业并没有利用好这个有效武器来抵御外侵,很多企业仍然处于低迷状态,这和公司的既有发展模式相关。我们最有竞争优势的就是廉价劳动力,所以一些轻工业,重工业,进出口等公司的效益非常可观,但金融危机的介入,以及劳动力的涨价,这些产业也是最为痛苦的。针对这种现状,企业发展模式的转型是否应该是我们首要考虑的呢?利用我们对于国民深入了解,将企业从规模产业化发展,转型到服务价值型增长呢?从以往的提供产品,探索客户更深层次的服务需求,这是不是以后我们应该走的路呢?

         中国化发展,不仅为满足中国市场规律而遵循的规范,更应该是中国企业可挖掘的最宝贵资源

  • Web2.0网站性能调优实践(转载)

    2009-02-15 13:56:14

    Web2.0网站性能调优实践

    当前web2.0革命风起云涌,web2.0强调服务,而服务最基本的要求是速度快和稳定,离开这两个谈功能强大和易用性都没有任何意义。本文介绍一些关于笔者运营一个web2.0网站的优化心得和经验,希望能够和大家共同探讨。
    Web2.0网站不同于以往以静态信息为主的网站架 构,以往的结构大体分为2层,一个是客户端浏览器,一个就是web服务器;而web2.0以动态和交互为主,一般是3层或者4层,在静态信息网站的结构上 的web服务器后端会增加应用服务器和数据库。一般会把浏览器和web服务器归为最上一层即为web层,应用服务器为中间一层,数据库为最底层。从优化角 度来讲,越上层优化获得益处越大,优化也是从上自下而来。
    Web层优化DNS的解析时间这个时间就是在用户第一次访问网站的时候产生,解析 时间会影响用户的访问感受,因此想要网站响应速度快,第一就是不要在DNS解析上产生问题。另外DNS的TTL时间也要考量,IE的DNS过期时间是30 分钟,TTL设置的比这个长一点就可以。另外在web服务器上使用keep-live也会减少DNS查询次数。
    降低浏览器发起请求的数量尽量降低浏览器发起请求的数量,就是说尽量能够让浏览器缓存任何可以缓存的东西。这样当用户访问过一次后,第二次访问可能会使得发起的请求数趋近1或者等于1,如果是静态的页面则可能是0。方法包括:
    把所有的样式表文件并为1个
    把所有的js文件并成1个
    图片尽量能够合成1张,这个跟以前不一样,现在大多数是adsl上网,反而是大量的零碎图片能够影响速度
    页面布局与样式页面采用xhtml,采用div+css布局,而把样式表和xhtml文件分开,一则能够降低xhtml文件大小,二则能够对样式表文件进行其他缓存处理。这里还有个ui设计的原则,ui跟系统结构一样,越简洁越好,这样整体页面代码会比较少,速度也会比较不错。
    JavaScript文件JavaScript文件也最好放到html文件外,原因同上。
    静态文件的优化方法a)目前大多数的浏览器都支持gzip压缩文件,因 此为文本、静态页面、样式表、JavaScript文件等可以压缩处理的文件进行压缩处理能够减少内容获取时间,一般压缩完的大小为原大小的 10-30%。这个在apache等web服务器上进行设置,笔者使用lighttpd的设置为:
    server.modules = (
          ….
          "mod_compress",
          …
    )
    compress.cache-dir="/usr/local/lighttpd/cache"
    compress.filetype = ("text/plain", "text/html", "text/css", "text/javascript")
    b)还可以在静态文件服务器前面增加缓存服务器比如squid,进一步增强客户端的访问性能。如果有好的财力,还可以使用一些商业的CDN加速服务。
    应用Cookie的注意事项Cookie的应用要注意,要限制cookie的应 用域和应用的目录以及过期时间。不然如果用户是第一次访问的话,可能连一个小小的静态图片都要发送cookie到服务器,这样增加了通信负载。另外要限制 cookie的大小,一个3k的cookie能够增加延迟达到80ms。
    提高页面速度页面由2-4个不同域名的服务器提供服务能够提高速 度,这个国外也有研究证明。比如主html文件由app.domain.com提供,样式表由style.domain.com提供,图片等由 img.domain.com提供,这样浏览器可以同时从多个服务器下载文件,速度就能够上去。但是最好不要超过4个。
    样式表文件位置把样式表文件放在页面的<head>,这样能够先读取。因为在ie中有个样式表的问题,样式表如果没有加载完会影响后面的html内容的页面显示,因此虽然html文件都已经在浏览器了,但是页面还是显示不出来。
    把JavaScript移到html文件末尾把JavaScript移到html文件末尾。为什 么这么做呢,因为JavaScript处理的过程中会阻塞后面的页面显示,并且也会使得http请求也被阻止。笔者的网站就有过这样的例子,网站上放了一 个合作方的JavaScript,结果每次访问时候感觉页面都停滞,用户体验特别差,后来让同事处理了一下,放到末尾等页面加载完了再显示在原有位置,一 下子就好了。
    尽量避免跳转尽量避免跳转比如301和302。如果必须的话,对301和302的页面添加过期头。笔者原来的单点登录就需要进行跳转,后来改进了不需要跳转,整体的速度效果就出来了。
    移除重复的脚本要移除重复的脚本,ie会对重复的脚本发起重复的http请求,大多数网站在运营一段时间都有可能出现这个情况,笔者的网站中就经常有市场人员添加的重复的广告脚本
    AJAX内容AJAX内容也是可以进行缓存的,同样可以压缩和缓存异步调用的xml、json等数据。
    对爬虫进行限制对爬虫进行限制,国内的一些爬虫非常厉害,并且不遵守robots规矩,经常有反应某某厉害爬虫把网站搞瘫的事件。怎么对爬虫进行限制呢,只能在web服务器上下功夫了,apache等服务器都能够进行限制,笔者的lighttpd限制10个并发的配置如下:  
    evasive.max-conns-per-ip = 10
    web层的优化目的就是极大的利用了浏览器的缓存特性,从而达到几乎是本地访问的速度,下图是笔者访问douban.com首页的效果图对比:

    前一列数据是空的缓存所需要下载的文件大小和http请求数量,后面是真实访问的带cache的情况,效果特别明显。http请求减少了95%,内容cache了82%。
    应用程序层优化应用服务器的优化Php的可以采用一些优化手段比如Zend Optimizer、eAccelerator、MMCache、Zend Performance Suite等
    Java的可以采用一些性能强的jdk、应用服务器,对jdk参数进行优化等等
    使用ETagETag就像版本控制服务器中的版本号一样,每次更新后的ETag是不一样的,而浏览器处理就类似版本服务器的客户端一样,先把版本号发到服务器请求。ETag的处理过程,先是Web服务器在响应的http头中发送ETag,比如这样:
    ETag: "1111-2222-3333"
    Last-Modified: Thu, 07 Oct 2007 15:20:18 GMT
    而浏览器如果再次请求该页面就会发送类似如下的头:
    If-None-Match: "1111-2222-3333"
    If-Modified-Since: Thu, 07 Oct 2007 15:20:18 GMT
    此时,如果该页面没有任何变更,则web服务器会响应一个304的头,并且不需要附带页面内容给浏览器(即不需要再动态生成页面内容),这样就大大减少了服务器的处理和网路通信负载。
    同步变异步同步变异步,在web2.0网站中经常有很复杂的处 理,比如一个用户的注册还需要发邮件等操作,有时候可能还有其他的处理,这样用户的等待时间比较长,并且容易出现错误。此种情况下,把其他处理变成异步 的,从而直接把页面尽快响应给用户。笔者的一个数据上传的程序也是如此处理,一大堆数据,上传时间可能就1-2秒,而处理时间可能长的需要接近10秒(需 要在数据库中进行上千次的插入操作),而在应用服务器容器内处理耗时则更长,笔者后来改成异步处理以后,用户满意度则大幅上升。
    使用缓存还是缓存,可能的情况下尽量使用缓存,毕竟现在内存非常便宜,用空间换取时间效率应该是非常划算的。尤其是对耗时比较长的、需要建立网络链接的,方法:采用memcached进行数据库或者常用数据的缓存;应用数据库缓冲池减少建立数据库连接的时间
    采用gzip压缩动态页面可能情况下,也可以采用gzip压缩动态页面。如果服务器较多,cpu负载不高,则可以考虑对动态页面增加gzip压缩功能
    集群处理访问压力大的时候,对应用服务器采用集群处理。
    应用服务器的优化主要是减少程序处理的时间,提高运行效率。
    数据库优化这个议题跟具体数据库关系比较大,议题也比较广泛,笔者就只简要列举一下:
    设置专门的DBA,专门负责数据库的安装、优化;对sql进行优化采用数据库集群和复制功能分担数据库压力。
    其他优化措施网站的优化涉及的方面比较多,其他方面涉及的还包括网站架构、操作系统、服务器硬件、网络设备、isp机房网络等等的调优。
    工具笔者用到的工具,都是firefox插件,所以firefox是必备的了:
    1、LiveHTTPHeaders (
    http://livehttpheaders.mozdev.org/)
    2、Firebug (
    http://getfirebug.com)
    3、YSlow (
    http://developer.yahoo.com/yslow/),要先装Firebug
    4、Web Developer (
    http://chrispederick.com/work/web-developer/)
    除了这些免费的工具外,还可以采用一些商业的网站性 能监测服务。一般网站性能监测服务商都会在不同的isp设置数据采集点,然后会定期模拟浏览器的访问对网站进行访问获取各种数据,比如dsn查询时间、第 一个包获取时间、整个页面加载时间等等,然后汇总到数据中心。数据中心则可以产生性能报表、不同时间的可访问率、哪个isp容易出问题、发出警报等等。如 果预算足够的话,可以采用这个服务。国外的有keynote、ip-label等,功能比较齐全,但是服务费用比较贵而且国内的点比较少。国内近些年也开 始涌现出一些厂商,比如基调网络。笔者使用的监测系统的图例:

    笔者网站3年不同阶段的优化过程优化的原则是尽量不去优化,在未发生性能问题的时候,没有必要去专门考虑细节的性能问题,当然大的结构应该是能够适应网站不断发展变化的。笔者的网站近3年的优化过程如下:
    1、开发完成,刚上线的时候,不做优化,用户量少,用了3台服务器。
    2、10万用户的时候,主要对sql进行了优化,还是3台服务器。
    3、10万用户到100万的过程中,采用了AJAX等,因此开始关注JavaScript的优化手段,访问量也快速上去,因此对静态文件进行分离并优化。服务器也进行了扩展,扩展到5台服务器。
    4、100万-200万用户,业务系统增加了很多,因此数据库采用了复制,程序方面应用了各种缓存处理,在数据库和程序之间增加了memcached进行数据缓存。
    5、在200万用户以上,主要在程序架构上做文章,对某些服务使用了集群。另外为了监测国内不同城市、isp的网络状况,使用了商业化的网站性能监测服务。
  • TD缺陷统计——Excel辅助导出

    2008-12-18 13:11:27

            此功能主要是收集我们自定义过滤条件的BUG列表,根据这个功能,我们可以开发很多我们的需求。

     

    Function Defects_ActionCanExecute(ActionName)

      On Error Resume Next

     

     IF ActionName="changelist"  then

     

         Dim i, j

         Dim a(300,300)

         Dim status

         msg1="请输入想过滤的状态,','号为分隔符"

         Title="状态选择"

         status = InputBox(msg1,Title)

         b = split(status,",")

         Set xlApp = CreateObject("Excel.Application")

         xlApp.Visible = True

         Set xlBook = xlApp.Workbooks.Open("D:\test1.xls")

         Set xlsheet = xlBook.Worksheets(1)

         xlsheet.Activate

     

        set com = TDConnection.Command

        dim str

        if ubound(b) = 0 then

        str = "'"&status&"'"

        else

           for i=0 to ubound(b)

              if i<>ubound(b)  then

                 str = str&"'"&b(i)&"'"&","

                 else

                 str = str&"'"&b(i)&"'"

              end if

           next

    end if

     

    'com.CommandText = "SELECT BG_BUG_ID,BG_STATUS,BG_DETECTED_BY,BG_PROJECT,BG_SUMMARY FROM BUG where convert(varchar(70),bg_bug_id) in (select distinct hs_key from history where convert(char(10),hs_change_date,120) = convert(char(10),getdate(),120) and hs_table_name = 'bug' and hs_new_value = '"&status&"')"

        com.CommandText = "SELECT BG_BUG_ID,BG_DETECTION_DATE,BG_RESPONSIBLE,BG_CYCLE_REFERENCE,BG_SEVERITY,BG_STATUS,BG_SUMMARY FROM BUG where  BG_STATUS in("&str&")"

        'com.CommandText = "SELECT BG_BUG_ID,BG_STATUS,BG_PROJECT,BG_SUMMARY FROM BUG where convert(varchar(70),bg_bug_id) in (select distinct hs_key from history where convert(char(10),hs_change_date,120) = convert(char(10),'2008-07-25',120) and hs_table_name = 'bug' and hs_new_value ='"&status&"')"

        Set RecSet = com.Execute

     

        a(1,1)="问题编号"

        a(1,2)="提交时间"

        a(1,3)="提交给"

        a(1,4)="所属模块"

        a(1,5)="严重级别"

        a(1,6)="受理状态"

        a(1,7)="SUMMARY"

     

     for i = 2 to RecSet.RecordCount

         for j = 0 to 6

          a(i,j+1)=RecSet(j)

         next

         RecSet.Next

     next

     

     for i=1 to  RecSet.RecordCount

         for j=1 to 7

              xlsheet.Cells(i,j) = a(i,j)

         next

     next

     

         xlBook.RunAutoMacros (xlAutoOpen)

         cmDialog.CancelError = False

         cmDialog.FileName = "BUG REPORT"

         cmDialog.DialogTitle = "Save Export File"

         cmDialog.DefaultExt = "*.xls"

         strFileName = cmDialog.FileName

         Set ōbjFileSystem = CreateObject("scrīpting.FileSystemObject")

         msg = MsgBox("成功导出!", vbOKOnly)

         end if

      Defects_ActionCanExecute = Project_DefaultRes

      On Error GoTo 0

    End Function

  • TD缺陷修改时间初始化

    2008-12-18 13:06:01

    BUG属性中的Modify往往不是我们需要的最后修改时间,所以我们需要从历史记录中进行刷新.

    这个功能可以扩展思路,其主要是帮助我们在进入项目后,将我们需要的内容进行同步更新.代码如下:

     

    Sub Defects_EnterModule

      On Error Resume Next

     

      set com = TDConnection.Command

          com.CommandText = "update BUG set BG_USER_04 = (select convert(varchar(10),max(HS_CHANGE_DATE),20) from HISTORY where convert(varchar(70),BUG.BG_BUG_ID) = HISTORY.HS_KEY and HISTORY.HS_TABLE_NAME = 'BUG' GROUP BY HISTORY.HS_KEY)"

      Set RecSet = com.Execute

     

      On Error GoTo 0

    End Sub
  • TD缺陷状态控制

    2008-12-18 12:58:53

    开发人员往往在修改BUG状态时,习惯性的不做一些备注,对此测试管理的时候很不方便,所以我们需要通过TD编程使备注编写强制化,代码如下:

     

    Function Defects_Bug_FieldCanChange(FieldName, NewValue)

          On Error Resume Next

     

         Defects_Bug_FieldCanChange = Project_DefaultRes

         On Error GoTo 0

     

         if FieldName = "BG_STATUS" then

            if  NewValue="Fixed"  then

                if Bug_Fields("BG_STATUS").Value="working" and  Bug_Fields("BG_DEV_COMMENTS").IsNull=true then

                     Msgbox "请增加注释内容"

                     Defects_Bug_FieldCanChange = False

                    Exit Function

                end if

            end if

       end if

         End Function
  • websphere性能监控分析——WAS内存使用

    2008-12-18 02:35:37

    1、问题描述:

    服务器的内存一直被支持占用1G,而使用内存很有规律的从600M增加到1G后,再释放到600M,空闲内存也配合使用内存而有规律的调节。发现这个现象后,确认应用与数据库无人在用,排除了有人操作服务器造成大的访问量的可能,同时日志也没有异常情况,所以再进行跟踪。跟踪发现,内存仍然如此,在很有规律的上下浮动,但是总占用内存不变,此处存在问题。

     

    2、问题推测:

    根据内存使用情况来看,可能存在两种状况,一部分可能是浮动的内存存在问题(从600M1G),一部分可能是固定内存存在问题(最低使用总是600M以上)。

    1)上下有规律的内存浮动,怀疑是否有数据在循环执行。

    2)使用内存量持续保持600M以上,怀疑内存中存在数据没有释放。

                               

                     图1:WAS内存使用情况

     

        根据开发部提供的《XXX9.5版升级实施工作进展情况(截至1026凌晨2点)》部分符合第一点的问题,但是也有不符合的地方。

       1)这个问题只有在XXX出现过 2)MMM一直运行正常,并为对数据库更新过

    由此推断不是开发部说的这个问题。 

        后来得到消息,数据中心人员对MMM的MDM更新过一个过滤的文件,然后重新启动应用,这里第二个推测就和这个举动紧密相连了。

        首先想到的是静态变量没有释放的问题,这里涉及到WAS的工作机制,WAS在重启一个应用的时候,是不会释放应用中静态变量所引用的内存的,只有重启WAS,内存才会被完全释放。根据这个原理,我找数据中心进行了咨询,确认是够是对包进行了更新,得到肯定的答案,然后确认是否在程序中引入了大量的静态变量,同样得到了肯定的答案,由此,我对推测了产生了相对确认的肯定。

  • websphere日志分析——程序隐患问题

    2008-12-18 02:21:59

            程序往往在我们使用的过程中并不会在页面显示什么异常,但是后台却报了严重的错误,原因是对于数据的处理和传输不严谨,比如查询无数据的处理、查询条件有NULL值、或者查询返回数据过大等等。

     

    (1) 连接对象 

    [08-12-3 8:49:10:993 CST] 0000065e SystemErr R java.sql.SQLException: ORA-00604: error occurred at recursive SQL level 1

    ORA-01000: maximum open cursors exceeded

       这个问题和WAS也有一定的关系,随WAS版本不同,其JDBC对于PreparedStatement缓存设置也不同,在咱们的程序中,如果出现这个问题,说明PreparedStatement

    \Statement对象的引用,并没有关闭。

          

           一般程序上

           pstmt = connection.prepareStatement(...);

           pstmt.executeUpdate();

        这样来使用,所以我们还需要加入一句

        pstmt = connection.prepareStatement(...);

           pstmt.executeUpdate();

           pstmt.close();

           这样就可以有效的防止此类问题的发生,也不容易造成内存溢出的错误。

           如果不及时关闭的话,DBMS会分配一个指针,实时对PreparedStatement对象进行遍历,加大系统开销。

         通过查看VSS上源代码,发现很多数据库连接对象都没有关闭,有很多没有关闭的,还有的是写了关闭,但似乎没有执行到,如下

     

       finally {

                         try {

                                if (!conn.isClosed()) {

                                       if (!conn.getAutoCommit()) {

                                              conn.rollback();

                                              conn.setAutoCommit(true);

                                              log

                                                            .error("TacticSearchServlet|Error while closing connection.");

                                       }

                                       conn.close();

                                }

                         } catch (Exception e) {

                                System.out.println("异常:"+e.getMessage());

                         }

     

        执行finally的时候,如果出错了,那么就进入了finallycatch,而finally try中才有数据连接对象的关闭。

        综上所述,需要开发检查PreparedStatement对象和Connection对象的关闭情况

     

    (2) 类型转换

    [08-12-3 9:00:12:092 CST] 00000681 SystemErr R java.lang.NumberFormatException: For input string: ""

       从错误日志找到当时是执com.hss.mcs.report.servlet.Sale_Analysis_Servlet,查看代码发现,这个属于“数据营销平台—数据销售分析”调用的,查看代码,发现是int I_jgbs=(new Integer(I_jgbs1)).intValue()这里对数据类型进行了转化,而I_jgbs1这个参数会取到空值,所以程序对转化也需要做一个修改。

211/212>
Open Toolbar