??xml version="1.0" encoding="utf-8" standalone="yes"?>
作者:Mark Levison 译者:赖勤?发布?2010q?1??/p>
现在已经到第十次q代开发周期了Q你的项目开发速度开始变慢。在之前的几个P代周期中Q团队没有像以前那样完成很多?#8220;故事场景”QstoriesQ。此外,最q在新的故事场景和回溯中却发现更多缺?bug)。项目经理知道,团队成员没有变,他们也花同样的时间工作。但是,客户会发问:“发生什么事情了Q这个团队还在努力工作吗Q?#8221;
很多敏捷团队的品改q率?50-500%Q可是你们的目看v来却貌似只有20-40%左右的改q率。这到底是怎么回事呢?在此我们找不C么大问题Q相反,只是有无数的问题。有Ӟq些只是一些ؓ了方便而用的捷径Q开发h员没有时间去清理q些修改Q,有时开发h员仅仅是不熟悉这中语a。还有一些问题就是,代码跟灌木丛一样凌乱,需要大q度的修整。所有这些都属于“技术债务”?/p>
什么是“技术债务”Q?/strong>
它就?#8220;那些内在的事物,现在你不去解冻I遗留下来Q不q完Q,它就会阻未来开?#8221;[Ward Cunningham]?表面上,应用E序看v来质量很高且状况良好Q但是这些问题却隐藏在下面?QAQ质量保证部门)甚至可能告诉你说Q这个应用程序真是不错,几乎找不到缺P但是其中仍然存在“技术债务”Q如果我们没有很好地理q设法降低这?#8220;技术债务”Q那么,E序~写和维护的代h最l将会超q它对客L价倹{?/p>
技术债务像信用卡一P会有很高的利息率Q就如同l团队留下了大量的帐务开销。这U情况下Q开销会体现在时间花费和解决问题所需的努力上面。开发团队拖延债务的时间越长,所U篏的利息就多Q会额外增加很多工作Q,付出的成本也p高?/p>
另外Q这q增加了实际的胦务支出:开发团队处理技术债务所p的时_可以用在对团队有价值的其它工作上。同Ӟq些难读的代码引L技术债务也让我们难以扑ֈ软g的缺陗再且,理解代码所损失的时间还可以用来做其它更有h值的事情呢?/p>
我们Z要篏U技术债务呢?
目~码初期Q不整理代码Q不写单元测试,也不做测试驱动开发,整个团队_制滥造出更多?#8220;故事场景”?q些问题通常都不会马上暴露出来,而@规蹈矩地~写代码往往需要更多的旉Q特别是在早期阶Dc?/p>
技术债务来自哪里Q?/strong>
解决问题
q个问题的ƈ不是一下子可以解决的,解决Ҏ需要通过几个q代周期。ƈ且,你需要耐心Qƈ要从多个角度L解决途径?/p>
解决Ҏ中的要点
Zq样的立场,你会发现问题Q也会拥有机会。你的问题是Q项目的基础代码一直在U篏技术债务Q但是这些债务已经开始下降了。然而,现在跟客LL于处理这些问题的资金会跟处理q些问题一样困难。你的机遇是Q提高了开发h员的技能;清楚地表达了理层对q项工作的支持,q有QY件的代码质量会不断改善,软g~陷的数目也会不断减。同时这也会很好的提高团队的整体开发能力?/p>
一、从数据的角度来看,数据包括Q收集、存储、分析(挖掘Q、展C、提取?/strong>兼顾目前的系l,攉、存储、挖掘、提取,q几个环节的pȝ需要加强。特别是攉和提取这块?/p>
׃历史的原因,加之没有pȝ规划q,之前的数据收集来源比较零散,q样D分析数据旉要从各个地方来同步数据。当业务多了之后Q这些ؕ七八p的来源够让h头疼了。这ơ规划的一个重点就是,建立一套游戏数据收集系l。游戏分析涉及的数据Q日志类Q都从这个系l中获取Q不再单独分析各自的业务数据。业务系l采用数据上报的方式Q按照固定的格式来上报数据。例如:d、注册、充倹{消耗等{?/p>
采用q套游戏数据攉pȝQ还有一个重要的原因。现在我们的游戏都是独立q营游戏Q我们是甲方Q,那么我们可以采用类D讯的办法Q事先定义好数据规范Q要求游戏方按照我们的格式上报相x据给我们。这h们的数据分析pȝ可以做到非帔R用。不接多少游戏Q分析和展示pȝ都统一?/p>
数据提取Q这里主要是指时数据。这是我们这边的一个顽疾。时数据其实包括两个部分:数据来源和数据分析。一个常见的需求就是:分析一堆帐P数据来源Q的后箋行ؓQ数据分析)。因Z时数据的业务规则复杂Qƈ且数据来源千奇百怪,之前采用q全手工、全自动的方式来实现Q但是都p|了。现在想到的一个解x案就是,Z游戏数据攉pȝ之上Q再开发一个时数据分析系l?/p>
游戏数据攉pȝl一了数据的来源和格式,方便存储和提取原始数据。这基本解决了数据来源的问题。时数据分析系l,可以事先实现常见的分析逻辑Q例如:d、留存、保有、付费h数、付贚w额、消耗等{)Q然后采用过滤器模式或包装器模式来实现。这其实是一个半自动化的Ҏ。系l的用户是开发h员和产品人员。开发完q套pȝ应该可以省掉60%以上的时数据Q务?/p>
另外Q只要数据都是来自这套游戏数据收集系l,存储、分析,包括挖掘都会单很多。存储都会在HDFS上,分析基本都用HiveQ挖掘用Mahout?/p>
游戏数据挖掘是需要单独发展的一块业务,特别是现在专注独立运营之后。目前这块我们还需要更多的旉来积累经验?/p>
二、从服务的角度来看,服务包括Q服务框架、服务管理、服务监?/strong>?/p>
服务也是一个大范畴。服务化框架、页面登录服务器、GM接口Q这些都属于服务相关的内宏V兼儡前的pȝQ这些内定w已经基本实现Q这ơ只是做比较大的版本改进?/p>
Q友情提C:本博文章Ƣ迎转蝲Q但h明出处:hankchenQ?a href="http://www.tkk7.com/hankchen">http://www.tkk7.com/hankchenQ?/p>
我打把自己在这斚w的实际经验写成系列文章,主要包括下面q些内容Q?/font>
1?/font>U上应用故障排查之一Q高CPU占用
2?/font>U上应用故障排查之二Q高内存占用
3、线上应用故障排查之三:高I/O占用Q包括磁盘I/O、网lI/O、数据库I/O{?/p>
4、线上应用故障排查之四:E序僉|
敬请期待Q?/p>
Q友情提C:本博文章Ƣ迎转蝲Q但h明出处:hankchenQ?a href="http://www.tkk7.com/hankchen">http://www.tkk7.com/hankchenQ?/strong>
搞Java开发的Q经怼到下面两种异常Q?/p>
1、java.lang.OutOfMemoryError: PermGen space
2、java.lang.OutOfMemoryError: Java heap space
要详l解释这两种异常Q需要简单重提下Java内存模型?/p>
Q友情提C:本博文章Ƣ迎转蝲Q但h明出处:hankchenQ?a href="http://www.tkk7.com/hankchen">http://www.tkk7.com/hankchenQ?/strong>
Java内存模型是描qJavaE序中各变量Q实例域、静态域和数l元素)之间的关p,以及在实际计机pȝ中将变量存储到内存和从内存取出变量这L低层l节?/p>
在Java虚拟ZQ内存分Z个代Q新生代Q?strong>NewQ、老生代(OldQ、永久代Q?strong>PermQ?/p>
Q?Q新生代NewQ新建的对象都存放这?/p>
Q?Q老生代OldQ存放从新生代New中迁U过来的生命周期较久的对象。新生代New和老生代Old共同l成了堆内存?/p>
Q?Q永久代PermQ是非堆内存的组成部分。主要存攑֊载的Classcȝ对象如class本nQmethodQfield{等?/p>
如果出现java.lang.OutOfMemoryError: Java heap space异常Q说明Java虚拟机的堆内存不够。原因有二:
Q?QJava虚拟机的堆内存设|不够,可以通过参数-Xms?Xmx来调整?/p>
Q?Q代码中创徏了大量大对象Qƈ且长旉不能被垃圾收集器攉Q存在被引用Q?/p>
如果出现java.lang.OutOfMemoryError: PermGen spaceQ说明是Java虚拟机对怹代Perm内存讄不够?/p>
一般出现这U情况,都是E序启动需要加载大量的W三方jar包。例如:在一个Tomcat下部|了太多的应用?/p>
从代码的角度QY件开发h员主要关注java.lang.OutOfMemoryError: Java heap space异常Q减不必要的对象创建,同时避免内存泄漏?/p>
现在以一个实际的例子分析内存占用的故障排查?/p>
通过top命oQ发现PID?004的Javaq程一直占用比较高的内存不释放Q?4.7%Q,出现高内存占用的故障?
惌v上一?a href=" http://www.tkk7.com/hankchen/archive/2012/05/09/377735.html">U上应用故障排查之一Q高CPU占用介绍的PS命oQ能否找到具体是哪个的线E呢Q?
ps -mp 9004 -o THREAD,tid,time,rss,size,%mem
遗憾的是Q发现PS命o可以查到具体q程的CPU占用情况Q但是不能查?strong>一个进E下具体U程的内存占用情c?
只好L其他Ҏ了,q好Java提供了一个很好的内存监控工具Q?font color="#ff0000">jmap命o
jmap命o有下面几U常用的用法Q?
•jmap [pid]
•jmap -histo:live [pid] >a.log
•jmap -dump:live,format=b,file=xxx.xxx [pid]
用得最多是后面两个。其中,jmap -histo:live [pid] 可以查看当前Javaq程创徏的活跃对象数目和占用内存大小?
jmap -dump:live,format=b,file=xxx.xxx [pid] 则可以将当前Javaq程的内存占用情况导出来Q方便用专门的内存分析工P例如QMATQ来分析?
q个命o对于分析是否有内存泄漏很有帮助。具体怎么使用可以查看本博的另一文章:利用Eclipse Memory Analyzer ToolQMATQ分析内存泄?/font>
q里详细介绍下jmap -histo:live [pid] 命oQ?/strong> 从上囑֏以看出,int数组、constMethodKlass、methodKlass、constantPoolKlass都占用了大量的内存? 特别是占用了大量内存的int数组Q需要仔l检查相关代码? 最后,ȝ下排查内存故障的Ҏ和技巧有哪些Q?/strong> 1、top命oQLinux命o。可以查看实时的内存使用情况?nbsp; 2、jmap -histo:live [pid]Q然后分析具体的对象数目和占用内存大,从而定位代码? 3、jmap -dump:live,format=b,file=xxx.xxx [pid]Q然后利用MAT工具分析是否存在内存泄漏{等? Q友情提C:本博文章Ƣ迎转蝲Q但h明出处:hankchenQ?a href="http://www.tkk7.com/hankchen">http://www.tkk7.com/hankchenQ?/strong>
]]>
Q友情提C:本博文章Ƣ迎转蝲Q但h明出处:hankchenQ?a href="http://www.tkk7.com/hankchen">http://www.tkk7.com/hankchenQ?/strong>
以我们最q出现的一个实际故障ؓ例,介绍怎么定位和解册c问题?/p>
Ҏtop命oQ发现PID?8555的Javaq程占用CPU高达200%Q出现故障?/p>
通过ps aux | grep PID命oQ可以进一步确定是tomcatq程出现了问题。但是,怎么定位到具体线E或者代码呢Q?/p>
首先昄U程列表:
ps -mp pid -o THREAD,tid,time
扑ֈ了耗时最高的U程28802Q占用CPU旉快两个小时了Q?
其次需要的U程ID转换?6q制格式Q?/b>
printf "%x\n" tid
最后打印线E的堆栈信息Q?/b>
jstack pid |grep tid -A 30
扑ֈ出现问题的代码了Q?
现在来分析下具体的代码:ShortSocketIO.readBytes(ShortSocketIO.java:106)
ShortSocketIO是应用封装的一个用短连接Socket通信的工L。readBytes函数的代码如下:
public byte[] readBytes(int length) throws IOException {
if ((this.socket == null) || (!this.socket.isConnected())) {
throw new IOException("++++ attempting to read from closed socket");
}
byte[] result = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
if (this.recIndex >= length) {
bos.write(this.recBuf, 0, length);
byte[] newBuf = new byte[this.recBufSize];
if (this.recIndex > length) {
System.arraycopy(this.recBuf, length, newBuf, 0, this.recIndex - length);
}
this.recBuf = newBuf;
this.recIndex -= length;
} else {
int totalread = length;
if (this.recIndex > 0) {
totalread -= this.recIndex;
bos.write(this.recBuf, 0, this.recIndex);
this.recBuf = new byte[this.recBufSize];
this.recIndex = 0;
}
int readCount = 0;
while (totalread > 0) {
if ((readCount = this.in.read(this.recBuf)) > 0) {
if (totalread > readCount) {
bos.write(this.recBuf, 0, readCount);
this.recBuf = new byte[this.recBufSize];
this.recIndex = 0;
} else {
bos.write(this.recBuf, 0, totalread);
byte[] newBuf = new byte[this.recBufSize];
System.arraycopy(this.recBuf, totalread, newBuf, 0, readCount - totalread);
this.recBuf = newBuf;
this.recIndex = (readCount - totalread);
}
totalread -= readCount;
}
}
}
问题出在标U的代码部分。如果this.in.read()q回的数据小于等?Ӟ循环׃直进行下M。而这U情况在|络拥塞的时候是可能发生的?
至于具体怎么修改q业务逻辑应该怎么对待q种Ҏ情况了?
最后,ȝ下排查CPU故障的方法和技巧有哪些Q?/strong> 1、top命oQLinux命o。可以查看实时的CPU使用情况。也可以查看最q一D|间的CPU使用情况? 2、PS命oQLinux命o。强大的q程状态监控命令。可以查看进E以及进E中U程的当前CPU使用情况。属于当前状态的采样数据? 3、jstackQJava提供的命令。可以查看某个进E的当前U程栈运行情c根据这个命令的输出可以定位某个q程的所有线E的当前q行状态、运行代码,以及是否死锁{等?/font> 4、pstackQLinux命o。可以查看某个进E的当前U程栈运行情c? Q友情提C:本博文章Ƣ迎转蝲Q但h明出处:hankchenQ?a href="http://www.tkk7.com/hankchen">http://www.tkk7.com/hankchenQ?/strong>
]]>
Q友情提C:本博文章Ƣ迎转蝲Q但h明出处:hankchenQ?a href="http://www.tkk7.com/hankchen">http://www.tkk7.com/hankchenQ?/strong> Ҏl验Q应该是E序有死锁情况,于是在线上运行“jstack –F <pid>”命令,xU程堆栈dump下来?/font> 但是Q发现这个命令老是报下面的错误Q?/font> Thread 27316: (state = BLOCKED) U上环境是: Linux 2.6.18-194.el5 x86_64 x86_64 x86_64 GNU/Linux java version "1.6.0_21" l过分析发现Q这是JDK6u23之前版本的一个BugQ将JDK升到最新版本(1.6.0_31Q就可以解决问题了?/p> Q友情提C:本博文章Ƣ迎转蝲Q但h明出处:hankchenQ?a href="http://www.tkk7.com/hankchen">http://www.tkk7.com/hankchenQ?/strong>
Error occurred during stack walking:
sun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.debugger.DebuggerException: get_thread_regs failed for a lwp
Java(TM) SE Runtime Environment (build 1.6.0_21-b04)
Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01, mixed mode)
]]>
0. 不要试图一下子搞懂整个目
好好考虑一下,Z么理解项目代码是W一位的Q大部分情况是你被要求修复一个bug或者加强系l已有功能。你要做的第一件事情不是理解整个项目的架构。当寚w目进行维护时Q这P理解整个目架构Q可能会对你造成巨大的压力?/p>
即便是有着10q可靠编E经验的Java开发者可能也没有理解目的核心工作机Ӟ管他们可能已经在这个项目工作超q一q_假设他们q原始开发h员)。比如,对于认证机制或事务管理机制?/p>
他们是怎么做的Q他们对于自p责的部分非常了解Qƈ且能够交付h值给组。每天的交付价D比了解一些以后还不确定有没有的东襉K要的多?/p>
1. x于尽快交付h?/strong>
那我是否定了你对于项目架构理解的热情了么Q完全不。我只是要求你尽早的交付价|一旦你开始一个项目,搭徏了开发环境,你就不应该花一两周旉才交付什么,无论他的规模大小。假如你是一个有l验?span class="wp_keywordlink" style="padding-right: 0px; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">E序?/a>却两周都没有M交付Q你的经理怎么会知道你是真的在工作q是在看新闻?/p>
所以交付可以大家都轻松v来。不要认Z能够做有价值的交付前必ȝ解整个项目。这是完全错误的。加一Djavascript的验证代码对业务很有h|l理能够通过你的交付辑ֈ对你的信仅R这栯够向上领导证明你的贡献以及员工价倹{?/p>
日复一日,在你不断修复bug及增强功能之后,p够慢慢开始理解项目架构。不要低估对pȝҎ面面理解旉要花费的旉。花3-4天理解认证机Ӟ2-3天理解事物管理。这些都是依靠之前的怼目的经历,但关键还是要花时间才能透彻的理解。要在日常工作中挤出旉Q不要向l理要求特定的时间来做这些?/p>
找找目是否有一些不断维护的单元试用例。有效的单元试用例是理解大型项目代码的很好途径。单元测试能够帮助理解代码片D,包括一个单元的外部接口Q单元如何被调用以及q回内容Q及其内部实玎ͼ调试单元试比调试整个实际用例简单许多)?/p>
你如果能够很好的理解一些内容,写一些笔讎ͼ或者画一些类图、时序图、数据模型图Q以便你或日后其他的开发者维护?/p>
2. l护大型目所必须的技?/strong> 你能从事当前的工作,必然已经h良好的java技术。我们来谈谈能够让你在新目中良好表现的其他技能。大部分旉Q你在项目中的Q务是修复bug和增强功能?/p>
有两很重要的技能能够协助你l护大型目代码?/p>
2.1 能够q速发现需要的c?/strong> 在Q何维护活动中Q无论是修复bug或增强功能,W一个动作就是识别出当前修复或增强的用例中调用的cR当你定位到需要修复或增强的类/ҎQ就已经完工了一半?/p>
2.2 能够分析变更的媄?/strong> 当你在完成必要的修改或增强工作后Q最重要的就是要认你的修改没有破坏代码的其他部分。你要用你的java技术及对其他框架的理解扑և变更可能影响的部分。下面有两个单的例子详细描述了最后提及的情况Q?/p>
aQ当cA的equals()Ҏ变更后,调用一个保护A实例的List的contains()Ҏ时就会被影响到。若Java知识不够Q很难考虑到这L影响?/p>
bQ在一个web目中,我们假设“user id”保存在session中。一个新入程序员可能?#8220;user id”中加入一些信息作为bug修复的方法,但是却不知道会媄响到那些兌“user id”的用例?/p>
当你提高了如上两个技能,管你对目不是非常了解Q但大部分的l护d会变得简单很多。若你修复一个bugQ你会定位ƈ修复q个bugQƈ且保证变更不会破坏项目的其他部分。若你增强或加入一个特性,基本上你只需要模仿现有的Ҏ用相似的设计?/p>
在一个在UK行项目中Qؓ什?#8220;查看账户摘要”?#8220;查看交易历史”的设计需要巨大的差别呢?如果你理解了“查看账户摘要”的设计,完全可以模仿开发出“查看交易历史”的功能?/p>
׃复bug和增强来_你不必完全理解所?000个类的工作内容和代码如何q行来推动系l。你若有上面的技能,p很快定位需要修改的代码的部分,使用良好的java和框架技能修复,保证变更不会破坏目的其他部分ƈ交付Q尽你可能只知道一部分项目的设计?/p>
3. 使用工具扑ֈ需要的变更内容以及变更产生的媄?/strong> l箋我们快交付的主题,你应当寻N些能够通过量的了解目但能帮助你尽快实施交付的工具作ؓ辅助?/p>
3.1 q速发现需要变更内容的工具 无论是修复bugq是pȝ增强Q首先都要找到该用例调用的你需要修改的cdҎ。基本有两种方式理解一个用例的工作方式Q静态代码分析和q行时分析?/p>
源码分析l计扫描所有代码ƈ且展C类之间的关pR市Z有很多设备与工具。比如:ArchitexaQ?AgileJQ?UModelQ?Poseidon{?/p>
所有的静态代码分析工L点在于无法确切展C用例中cLҎ的运行时调用情况。因此Java新加入了Ҏ,如回调机Ӟcallback patternsQ。如静态分析工h法推断出当页面提交按钮被点击时哪个Servlet被调用了?/p>
q行时分析工兯够展C类和方法在用例q行时的状态。工具包括:MaintainJQ?DiverQjSondeQJava Call Tracer{。这些工具可以捕莯行时的堆栈状态,q以此ؓ一个用例生成序列图和类图?/p>
序列囑ֱCZ该用例在q行时所有调用的Ҏ。若你在修复一个bugQ那q个bug很可能就是这些被调用的方法之一?/p>
若你在增强已有功能,利用序列囄解调用流E然后再修改。可能是新增一个验证,修改DAO{?/p>
若你在新增功能,扑ֈ一些相似的Ҏ,利用序列囄解调用流E然后模仿开发新功能?/p>
要小心挑选运行时分析工具。信息过多是q类工具的主要问题。选择一些提供简单过滤无效信息ƈ能够方便的查看各U视囄工具?/p>
3.2 q速发现需要变更内容的工具 若单元测试有效,可以通过q行单元试发现变更有没有破坏其他测试用例。有效维护ƈ且覆盖大型企业应用的单元试q是比较的。下面有一些针对该情况的工兗?/p>
仍然是有两种技术静态代码分析和q行时分析可以用。市Z有很多静态代码分析工具可用。如QLattix, Structure101, Coverity, nWire and IntelliJ’s DSM?/p>
l定一个变更后的类Q上q工具均可识别对该类存在依赖的类的集合。开发者需要根据这些信?#8220;猜测”可能产生影响的用例,因ؓq些工具无法展示q行时类之间的调用关pR?/p>
市场上的可以用于q行时媄响分析的工具q不多,除了MaintainJ。MaintainJ先捕获在一个用例中调用的所有类和方法。当所有用例的上述信息都被捕获之后Q就很容易发现类的变更对用例的媄响。MaintainJ能够有效工作的前|条件就是项目的所有用例都应当先运行一遍,以便能够获得q行时的依赖关系?/p>
MQ目前你在迅速准分析变更媄响方面,q是可以从工具中获得有限的帮助。首先根据需要实施一些媄响分析,然后Ҏ自己或小l其他高U成员评审来判断变更的媄响。你可能需要上面提到的工具对你的判断进行反复确认?/p>
4. 对上q内容的两个忠告 4.1 不要降低代码质量 Z快速交付,所以没有全盘理解架构,但绝不能以降低代码质量ؓ条g。下面是一些你可能因ؓ只考虑快速交付而引发的代码质量问题?/p>
因ؓ修改代码涉及到很多的依赖Q所以新增代码相对而言风险较小。例如,?个用例都调用了某个方法。ؓ了改q某个用例,你需要修改这个方法的实现。最单的做法是复制q个ҎQ重命名Q然后在改进的用例中调用新方法。千万不要这么做。代码冗余绝Ҏ非常有害的。尝试对Ҏq行包装或者重写,甚至是直接修改,然后重新试所有用例,通常停下来想一惻I然后亲手d施,是一个比较好的方式?/p>
另一个例子是?#8220;private”Ҏ改ؓ“public”Q得别的类也可以调用。尽量不要将非必ȝ部分暴露出来。假如ؓ了更好的设计需?span class="wp_keywordlink" style="padding-right: 0px; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">重构Q就应当着手去做?/p>
大部分应用都有确定的l构和模式来实施。修复或增强E序Ӟ认你没有偏这L模式。若对约定不定Q请其他的高U开发者来审核你的变更。若你必d一些违背约定的实施Q尽量放|于一个规模较的cMQ一?00行代码的cM的私有函数应当不会媄响应用的整体设计Q?/p>
4.2 不要停止深入理解目架构 按照文章列出的方式,假设你能够在寚w目了解较的情况下进行交付ƈ以此持箋下去Q可能你会停止对目架构的深入了解。这样从长远角度来说对你的职业生涯没有帮助。当你的l验增加Ӟ你应当承担比较大的模块Q务。如构徏一个完整的新特性或者修攚w目的一些基设计{较大的改进。当你能够做q些改进Ӟ你对目的整体架构应该相当了解。文中列丄Ҏ是让你在最短的旉内提升自己,而不是阻止你完整理解整个目?/p>
5. l论 整篇文章集中在对目q行必要了解的前提下q行快速交付。你可以在不降低代码质量的前提下q么做?/p>
若修复一个bugQ迅速定位ƈ修复。有必要可以使用q行时分析工兗若新增一个特写,可以L怼特写Q理解流E(有必要用工Pq编写?/p>
或许q些听v来很单,但是实用吗?当然。但前提是你有良好的java技术以及对框架_了解才能先修改代码,然后对变更媄响进行分析。对变更影响的分析比实施变更需要更多的技巧。你可能需要高U开发h员协助你分析变更影响?/p>
大约?0%的IT可操作预用于简单的bug修复和功能增强。根据文中的Q对于维护活动中的经费的节省应当q是很有帮助的?/p>
作?Choudary Kothapalli 也是 MaintainJ 目的徏立者?/p>
英文原文Q?a class="external" style="padding-right: 0px; padding-left: 0px; padding-bottom: 0px; margin: 0px; color: #0b5c77; padding-top: 0px; text-decoration: none" target="_blank">Choudary Kothapalli
转蝲自伯乐在U?nbsp;http://blog.jobbole.com/16526/
利用Hadoop分析BHO上报日志Ӟ发现很多日志文g会出C面的错误Q?
卛_mapl束的时候抛出Java堆栈溢出异常Q?/p>
Q友情提C:本博文章Ƣ迎转蝲Q但h明出处:hankchenQ?a href="http://www.tkk7.com/hankchen">http://www.tkk7.com/hankchenQ?/strong>
首先讄下面的参敎ͼ
发现q是解决不了问题。开始怀疑代码问题,于是q行了一pd的优化: 主要的优化是Q在map和reduceE序中,重用key和value对象。但是发现还是解决不了问题。ƈ且mapred.child.java.opts讄3G也无于事?
没有办法Q只好l找原因。最后发C个规律:报这个异常出错的日志不一定是最大的日志?
只好使用最后一招了Q直接分析报错时的Java堆内存情况! 主要是下面的几类q程Q?
同时Q关注每台机器的top命o输出Q可以从内存的用情况中发现主要是哪台机器出问题Q然后重点导台机器的Java堆参敎ͼ
jmap -dump:live,format=b,file=heapt0923.bin pid
剩下来的是?data/bhopid_output/heapt0923.binq个文g复制到本圎ͼ利用Eclipse Memory Analyzer Tool q行分析Q?
下面是分析的l果Q?
发现有两个内存泄漏的情况Q?
1?
2?/p>
扑ֈҎ原因Q说明日志文件有q样很大的空记录D的!在代码中把这些记录忽略掉卛_Q?/p>
Q友情提C:本博文章Ƣ迎转蝲Q但h明出处:hankchenQ?a href="http://www.tkk7.com/hankchen">http://www.tkk7.com/hankchenQ?br />
再次出现异常的时候,把集里面所有的机器的Hadoopq程的堆内存导出来分析!
]]>
优化的地Ҏ及:
1.减少重复代码Q保证功能修改只会发生在一个地斏V?/p>
2.优化界面Q布局更加合理Q美观?/p>
3.优化SQL语句Q提高性能?/p>
4.JS文g的整合,公用的函数提取出来成为单独的文gQ减HTTPh的次敎ͼ览器缓存)Q同时也减少当前面的大?/p>
5.加了~存模块
l过q些优化之后Q系l性能提升不少。最重要的是Q系l的可维护性大大地提高了。相信以后增加功能不会那么篏了。看来连l两个晚上的加班时值得的?/p>