`
asdic
  • 浏览: 123595 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

JProfiler2

    博客分类:
  • Java
阅读更多

利用JProfiler对应用服务器内存泄漏问题诊断一例(转)关键字: java 在中间件应用服务器的整体调优中,有关于等待队列、执行线程,EJB池以及数据库连接池和Statement Cache方面的调优,这些都属于系统参数方面的调优,本文主要从另外一个角度,也就是从应用的角度来解决中间件应用服务器的内存泄露问题,从这个角度来提高系统的稳定性和性能。 项目背景 问题描述 某个大型项目(Use Case用例超过300个),在项目上线后,其Web应用服务器经常宕机。表现为: 1. 应用服务器内存长期不合理占用,内存经常处于高位占用,很难回收到低位; 2. 应用服务器极为不稳定,几乎每两天重新启动一次,有时甚至每天重新启动一次; 3. 应用服务器经常做Full GC(Garbage Collection),而且时间很长,大约需要30-40秒,应用服务器在做Full GC的时候是不响应客户的交易请求的,非常影响系统性能。 Web应用服务器的物理部署 一台Unix服务器(4CPU,8G Memory)来部署本Web应用程序;Web应用程序部署在中间件应用服务器上;部署了一个节点(Node),只配置一个应用服务器实例(Instance),没有做Cluster部署。 Web应用服务器启动脚本中的内存参数 MEM_ARGS="-XX:MaxPermSize=128m -XX:MaxNewSize=512m -Xms3096m -Xmx3096m -XX:+Printetails -Xloggc:./inwebapp1/gc.$$" 可以看出目前生产系统中Web应用服务器的内存分配为3G Memory。 Web应用服务器的重要部署参数 参数名称 参数值 参数解释 kernel.default(Thread Count) 120 执行线程数目,是并发处理能力的重要参数 Session Timeout 240分钟(4小时) HttpSession会话超时 分析 分析方法 内存长期占用并导致系统不稳定一般有两种可能: 1. 对象被大量创建而且被缓存,在旧的对象释放前又有大量新的对象被创建使得内存长期高位占用。 表现为:内存不断被消耗、在高位时也很难回归到低位,有大量的对象在不断的创建,经过很长时间后又被回收。例如:在HttpSession中保存了大量的分页查询数据,而HttpSession的会话超时时间设置过长(例如:1天),那么在旧的对象释放前又有大量新的对象在第二天产生。 解决办法:对共享的对象可以采用池机制进行缓存,避免各自创建;缓存的临时对象应该及时释放;另一种办法是扩大系统的内存容量。 2. 另一种情况就是内存泄漏问题 表现为:内存回收低位点不断升高(以每次内存回收的最低点连成一条直线,那么它是一条上升线);内存回收的频率也越来越高,内存占用也越来越高,最终出现"Out of Memory Exception"的系统异常。 解决办法:定位那些有内存泄漏的类或对象并修改完善这些类以避免内存泄漏。方法是:经过一段时间的测试、监控,如果某个类的对象数目屡创新高,即使在JVM Full GC后仍然数目降不下来,这些对象基本上是属于内存泄漏的对象了。问题定位 这里请看5月份 Web应用服务器的内存回收图形: 《注意:5月18日早上10点重新启动了Web服务器,5月20日早上又重新启动了Web服务器。》 在Web应用重要部署参数中,我们知道:Session的超时时间为4个小时,我们在监控平台也观测到:在18日晚上10点左右所有的会话都过期了,从图形一中也能看出18日晚上确实系统的内存有回收到40%(就象股票的高位跳水); 从图形一(5月18日)中我们也能看到Full GC回收后的内存占用率走势(红色曲线),上午基本平滑上升到20%(内存占用率),中午开始上升到30%,下午上升到40% 从图形二(5月19日)中我们也能看到Full GC回收后的内存占用率走势(红色曲线),上午又上升到了60%,到下午上升到了70%。 从黄色曲线(GC花费的时间,以秒为单位),Full GC的频率也在增快,时间耗费也越来越长,在图形一中基本高位在20秒左右,到19日基本都是30-40秒之间了。 图形一 5月18日 图二 通过上述分析,我们基本定位到了Web应用服务器的内存在高位长期占用的原因了:是内存泄露!并且正是由于这个原因导致系统不稳定、响应客户请求越来越慢的。 解决方法 方法如下: 我们从图形二中发现,在8.95(将近9点钟)到9.66(将近9点40)期间有几次Full GC,但是有内存泄漏,从占用率40%上升到50%左右,泄漏了大约10%的内存,约300M; 我们在自己搭建的Web应用服务器平台(应用软件版本和生产版本一致)做这一阶段相同的查询交易;表明对同一个黑盒(Web应用)施加同样的刺激(相同的操作过程和查询交易)以期重现现象; 我们使用Jprofiler工具对Web应用服务器的内存进行实时监控; 做完这些交易后,用户退出系统,并等待Web应用服务器的HttpSession超时(我们这里设置为15分钟); 我们对Web应用服务器做了两次强制性的内存回收操作。发现如下: 图三 如图三所示,内存经过HttpSession超时后,并强制gc后,仍然有大量的对象没有释放。例如:gov.gdlt.taxcore.comm.security.MenuNode,仍然有807个实例没有释放。 我们继续追溯发现,这些MenuNode首先存放在一个ArrayList对象中,然后发现这个ArrayList对象又是存放在WHsessionAttrVO对象的Map中,WHsessionAttrVO 对象又是存放在ExternalSessionManager的staic Map中(名称为sessionMap),如图四所示。 图四 我们发现gov.gdlt.taxcore.taxevent.xtgl.comm.WHsessionAttrVO中保存了EJBSessionId信息(登录用户的唯一标志,由用户id+登录时间戳组成,每天都不同)和一个HashMap,这个HashMap中的内容有: ArrayList: 内有MenuTreeNodes(菜单树节点) HashMap: 内有操作人员代码信息 CurrentVersion:当前版本号 CurrentTime:当前系统时间 WHsessionAttrVO这个对象的最终存放在ExternalSessionManager的static Map sessionMap中,由于ExternalSessionManager是一个全局的单实例,不会释放,所以它的成员变量sessionMap中的数据也不会释放,而Map中的Key值为EJBSessionId,每天登录的用户EJBSessionId都不同,就造成了每天的登录信息(包括菜单信息)都保存在sessionMap中不会被释放,最终造成了内存的泄漏。 图五 如上图所示:WHsessionAttrsVO对象中除了有一个String对象(内容是EJBSessionId),还有一个HashMap对象。 图六 如上图所示,这个HashMap中的内容主要有menuTreeNodes为key,value为ArrayList的对象和以czrydminfo为key,value为HashMap对象的数据。 图七 如上图所示:menuTreeNodes为key,value为ArrayList对象中包含的对象有许多的MenuNode对象,封装的都是用户的菜单节点。 图八 如上图所示,最顶层(Root)的初始对象为一个ExternalSessionManager对象,其中的一个成员变量为static (静态的),名称为:sessionMap,这个对象是singleton方式的,全局只有一个。 初步估量 我们从图形一和图形二中可以看出,每天应用服务器损失大约40%的内存,大约1G左右。 从图形四可以看出,当前用户(Id=24400001129)有807个菜单项(每个菜单项为一个MenuNode 对象实例,图形四中的这个实例的size为592 Byte),这些菜单数据和用户基本登录信息(czrydmInfo HashMap)也都存放在WHsessionAttrVO对象中,当前这个WHsessionAttrVO对象的size为457K。 我们做如下估算: 假设平均每天有4千人(估计值,这个数值仅仅是5月19日峰值的1/2左右)登录系统(有重复登录的现象,例如:上午登录一次,中午退出系统,下午登录一次),以平均每人占用200K(估计值,是用户id=24400001129 的Size的1/2左右)来计算,一天泄漏的内存约800M,比较符合目前内存泄漏的情况。当然,这种估计仍然需要经过实践的检验,方法是:当这次发现的内存泄漏问题解决后看系统是否还有其它内存泄漏问题。 方案 ExternalSessionManager类是当初某某软件商设计的用来解决Web服务器负载均衡的模块,这个类主要用来保存客户的基本登录信息(包括会话的EJBSessionId),以维护多个Web服务器之间的会话信息一致。 改进方案有两种: 从架构设计方面改进 实现Web层的负载均衡有很多标准的实现方式。例如:采用负载均衡设备(硬件或软件)来实现。 如果采用新的Web层的负载均衡方式,那么就可以去掉ExternalSessionManager这个类了。 从应用实现方面改进 保留当前的Web层的负载均衡设计机制,仅仅从应用实现方面解决内存泄漏问题,首先菜单信息不应该保存在ExternalSessionManager中。其次,增加对ExternalSessionManager类中用户会话登录信息的清除,有几种方式可以选择: 被动方式,当HttpSession会话超时(或过期)被Web应用服务器回收时清除相应的ExternalSessionManager中的过期会话登录信息。 主动方式,可以采用任务定时清理每天的过期会话登录信息或线程轮询清理。 采用新的会话登录信息存储方式,ExternalSessionManager的sessionMap中的key值不再以EJBSessionId作为键值,而是以用户id(EJBSessionId的前11位)代替。由于用户id每天都是一样的,所以不会造成内存泄漏。保存得登录信息也不再包含菜单节点信息,而只是登录基本信息。最多也只是保存整个系统所有的用户id及其基本登录信息(大约每个用户的登录信息只有1.5K左右,而目前这个系统的营业网点用户为1万左右,所以大约只占用Web服务器15M内存)。 实施情况 采用的方案:某某软件商采用了新的会话登录信息存贮方案,即:ExternalSessionManager的成员变量sessionMap中不再保存用户菜单信息,只保存基本的登录信息;存储方式采用用户id(11位)作为键值(key)来保留用户基本登录信息。 基本分析:由于基本登录信息只有1K左右,而目前内网登录的用户总数也只有8887个,所以只保存了大约10M-15M的信息在内存,占用量很小,并且不会有内存泄漏。用户菜单信息保存在session中,如果用户退出时点击logout页面,那么应用服务器可以很快地释放这部分内存;如果用户直接关闭窗口,那么保存在session中的菜单信息只有等会话超时后才会由系统清除并回收内存。 监控状况: 图九 如图九所示,ExternalSessionManager中只保留了简单的登录信息(Map中保存了WHsessionAttrVO对象),包括:当前版本(currentversion),操作人员代码基本信息(czrydmInfo),当前时间(currenttime)。 图十 如图十所示,这个登录用户的基本信息只有1368 bytes,大约1.3K 图十一 如图十一所示,一共有两个用户(相同的用户id)登录系统,当一个用户使用logout页面退出时,保留在session中的菜单信息(MenuNode)立刻释放了,所以Difference一栏减少了806个菜单项。 图十二 如图十二所示,当另外一个会话超时后,应用服务器回收了整个会话的菜单信息(MenuNode),图上已经没有MenuNode对象了。并且由于是同一个用户登录,所以保留在ExternalSessionManager成员变量sessionMap中的对象WHsessionAttrVO只有一个(id=24400001129),而没有产生多个,没有因为多次登录而产生多个对象的后果,避免了内存泄漏问题的出现,解决了前期定位的内存泄漏问题。 图十三 如图十三所示,经过gc内存回收后,发现内存回收比较稳定,基本都回收到了最低点,也证明了内存没有泄露。 结论与建议:从测试情况看,解决了前期定位的内存泄漏问题。 生产系统实施后的监控与分析 经过调优后,我们发现:在2005年6月2日晚9点40左右重新部署、启动了Web应用服务器(采用了新的调优方案)。经过几天的监控运行,发现Web应用服务器目前运行基本稳定,目前没有出现新的内存泄漏问题,下列图示说明了这一点 图十四 2005年6月2日 如图十四所示,6月2日晚21.7(21点42分)重新启动应用服务器,内存占用很少,大约为15%(请看红色曲线),每次GC消耗的时间也很短,大约在5秒以内(请看黄色曲线)。 图十五 2005年6月3日周五 如图十五所示,在6月3日周五的整个工作日内,内存的回收基本到位,回收位置控制在20%-30%之间,也就是在600M-900M之间(请看红色曲线的最低点),始终可以回收2G的内存供应用程序使用,每次GC的时间最高不超过20秒,Full GC平均在10秒左右,时间消耗比较短(请看黄色曲线)。 图十六2005年6月5日周日 如图十六所示,在周日休息日期间,Web应用服务器全天只做了大约4次Full GC(黄色曲线中的小山峰),时间都在10秒以内;大的Full GC后,内存只占用10%,内存回收很彻底。 图十七 2005年6月6日周一 如图十七所示,在周一工作日期间,内存回收还是不错的,基本可以回收到30%(见红色曲线的最低点),即:占用900M内存空间,剩余2G的内存空间;Full GC的时间大部分控制在20秒以内,平均15秒(见黄色曲线)。 图十八 2005年6月7日周二 如图十八所示,在6月7日周二早上,大约8:30左右,Web应用服务器作了一次Full GC,用了10秒的时间,把内存回收到了10%的位置,为后续的使用腾出了90%的内存空间。内存回收仍然比较彻底,说明基本没有内存泄漏问题。 经过这几天的监控分析,我们可以看出: Web应用服务器的内存使用已经比较合理,内存在工作日的占用在20%至30%之间,约1G的内存占用,有2G的内存空间富裕;而在空闲时间(周日,每天的凌晨等)内存可以回收到10%,有90%的内存空间富裕; Web应用服务器的Full GC的次数明显减少了并且每次Full GC占用的时间也很少,基本控制在10-20秒之间,有的甚至在10秒以内,明显改善了内网应用服务器内存的使用; 从6月2日重新部署之后,Web应用服务器没有出现宕机重启的现象。 总结 通过本文,我们可以看到,内存的泄露将会导致服务器的宕机,系统性能就更别说了。对于系统内存泄露问题应该从服务器GC日志方面进行早诊断,使用工具早确认并提出解决方案,排除内存泄露问题,提高系统性能,以规避项目风险。

分享到:
评论

相关推荐

    jprofiler详细使用介绍

    jprofiler 详细使用介绍 jprofiler 是一款功能强大的 Java 性能分析工具,能够帮助开发者检测 Java 应用程序中的性能瓶颈、内存泄漏和死锁等问题。下面将详细介绍 jprofiler 的安装、注册和使用过程。 安装 ...

    jprofiler

    jprofiler

    JProfiler

    2. **CPU使用率**:查看哪些方法占用了CPU资源,可以定位到性能消耗较大的代码片段。 3. **线程分析**:检查线程状态,找出阻塞、等待或死锁的情况,优化并发性能。 4. **SQL查询**:如果应用涉及到数据库操作,...

    jprofiler7.2.X注册码 JProfiler入门教程(中文)

    2. **工作界面**:介绍JProfiler的主界面布局,包括各个面板的功能,如概述、内存、CPU、线程、SQL等视图。 3. **连接模式**:讲解本地连接和远程连接的区别,以及如何配置JProfiler来连接到正在运行的Java应用。 ...

    jprofiler_linux_4_3_2.tar.gz 和 JProfiler在Linux上的安装和使用.rar

    提供的压缩包"jprofiler_linux_4_3_2.tar.gz"是专为Linux设计的JProfiler版本,我们需要先将其解压。在终端中,通过以下命令可以完成解压操作: ```bash tar -zxvf jprofiler_linux_4_3_2.tar.gz ``` 解压完成后,...

    JProfiler11安装包及注册机

    2. **内存分析**:对于内存泄漏的检测,JProfiler11提供了强大的内存分析模块。它可以监控对象的创建、生存和销毁,帮助找出潜在的内存泄漏问题。 3. **线程分析**:通过可视化的方式展示线程状态,帮助开发者理解...

    jprofiler9+中文使用手册

    2. **JProfiler9中文使用手册** 中文使用手册是针对中国开发者的重要资源,它使得理解工具的功能和操作变得更加直观易懂。手册通常包括以下几个部分: - **安装与启动**:详细指导如何在不同操作系统上下载、...

    JProfiler11+注册机+使用手册

    2. **内存分析**: 内存泄漏是Java应用中常见的问题。JProfiler提供实时的堆内存分析,可以显示对象的分配路径,帮助你定位并解决内存泄漏问题。此外,其垃圾收集分析功能可以帮助理解GC行为,优化内存配置。 3. **...

    IDEA-JProfiler插件+JProfiler软件.zip

    在提供的压缩包文件中,包含了两个JProfiler的版本:`jprofiler_windows-x64_9_2_1.exe`,适用于Windows 64位系统的JProfiler安装程序,以及两个IDEA的JProfiler插件:`idea-jprofiler-18.3.zip`和`idea-jprofiler-...

    JProfiler安装及使用

    ##### 2. 配置 Windows 端 JProfiler - 安装完成后,打开 JProfiler 程序,在主界面上选择“Session Integration Wizards”>“New Remote Integration”来配置连接远程计算机。 - 在弹出的窗口中: - **连接类型**...

    jprofiler 注册码+安装包

    2. **CPU使用率监测**: JProfiler的CPU Profiling功能可以详细地记录和分析代码执行的时间,找出CPU资源消耗高的地方。这包括方法级别的调用时间统计,帮助开发者识别哪些函数或方法是性能瓶颈。 3. **线程分析**...

    jprofiler 6.06 JProfiler6 JProfiler6.x JProfiler6.* 注册机 注册码 序列号

    jprofiler 6.06 JProfiler6 JProfiler6.x JProfiler6.* 注册机 注册码 序列号 亲自在JProfiler6.06版本上测试通过可用

    jprofiler 7.2 key,jprofiler 7.2 注册码

    在探讨“jprofiler 7.2 key, jprofiler 7.2 注册码”这一主题时,我们首先需要了解jProfiler是什么以及它在Java应用性能分析领域扮演的角色。jProfiler是由eXtreme Labs开发的一款强大的Java性能分析工具,主要用于...

    jprofiler4.32安装破解文件+jprofiler4.32使用教程

    《JProfiler 4.32 安装与使用详解》 JProfiler是一款强大的Java性能分析工具,对于Java开发者而言,它是优化代码效率、排查内存泄漏和线程问题的得力助手。本文将详细介绍JProfiler 4.32的安装过程,并提供使用教程...

    JProfiler配置(WAS/Linux/tomcat/windows)

    - 将`jprofiler_linux_7_1_2.rpm`复制到Linux服务器的`/opt`目录,然后运行`rpm -ivh jprofiler_linux_7_1_2.rpm`进行安装。 **1.2 JProfiler客户端安装** - 在Windows上安装`jprofiler_windows_7_1_2.exe`,安装...

    JProfiler11

    **JProfiler11详解** JProfiler是一款强大的Java性能分析工具,尤其在JAVA应用程序的调优过程中扮演着至关重要的角色。它提供了丰富的功能,包括内存分析、CPU使用率监控、线程分析、方法 Profiling 和 SQL查询性能...

    jprofiler windows x64_7_2_3

    jprofiler windows 64位版本.

    JProfiler 9注册码

    2. **CPU性能分析**:通过收集方法调用频率、执行时间等数据,帮助开发者识别代码中的热点区域,进一步优化算法或实现方式。 3. **线程分析**:展示线程的状态变化及锁竞争情况,便于调试多线程应用中的死锁等问题。...

    jprofiler linux 和 windows 安装和配置

    2. **配置环境变量**:在系统环境变量中添加jProfiler路径至PATH中。 ##### 3.3 配置服务端 1. **使用Eclipse开发环境**:如果使用Eclipse开发启动JBoss等服务,可以通过在JDK选项中加入以下参数: ```plaintext ...

    jprofiler 6.0.6 含序列号

    2. **配置设置**:根据实际需求调整JProfiler的配置,如采样间隔、内存堆大小等,以获取更准确的分析结果。 3. **分析时机**:在适当的时间进行性能分析,如在高负载或特定业务场景下,可以更准确地发现性能问题。 ...

Global site tag (gtag.js) - Google Analytics