java内存泄露定位与分析
内存泄漏的检测定位和解决经验总结

内存泄漏的检测定位和解决经验总结内存泄漏是指程序在运行过程中,分配的内存没有被正确释放,导致内存资源无法被再次利用的情况。
由于没有及时释放内存,内存泄漏会导致系统的内存消耗不断增加,最终可能造成程序崩溃或者系统运行缓慢。
解决内存泄漏问题需要进行检测、定位和解决。
一、内存泄漏的检测1. 使用内存分析工具:可以使用一些专门的内存分析工具来检测内存泄漏问题,例如Valgrind、Memcheck等。
这些工具可以跟踪程序运行过程中的内存分配和释放,帮助定位内存泄漏的位置。
2.编写测试用例:通过编写一些针对性的测试用例,模拟程序运行过程中常见的内存分配和释放场景,观察内存的使用情况。
如果发现内存占用持续增长或者没有被及时释放,就可以判断存在内存泄漏问题。
3.监控系统资源:通过监控系统的资源使用情况,如内存占用、CPU使用率等,可以观察系统是否存在内存泄漏的迹象。
如果发现系统的内存占用不断增加,并且没有明显的释放情况,就需要进一步检查是否存在内存泄漏。
二、内存泄漏的定位1.使用日志输出:通过在程序中添加日志输出语句,记录程序运行过程中的重要信息,特别是涉及内存分配和释放的地方。
通过观察日志输出,可以发现是否有内存没有被正确释放的情况。
2.代码分析:通过代码分析,找出可能导致内存泄漏的地方。
常见的内存泄漏问题包括:不恰当的内存分配和释放顺序、不正确的内存释放方式、内存分配大小不匹配等。
对于涉及动态分配内存的地方,要特别关注是否有被遗漏的释放操作。
3.堆栈跟踪:当发现内存泄漏问题比较复杂或者难以定位时,可以使用堆栈跟踪来追踪内存分配和释放的调用路径,找出内存泄漏的具体位置。
在调试过程中,可以通过打印调用栈来获取函数调用的过程,进而确定哪个函数没有正确释放内存。
三、内存泄漏的解决1.及时释放内存:在程序中,所有动态分配的内存都需要及时释放。
对于每个内存分配操作,都要确保相应的释放操作存在,并且在适当的时候进行调用。
java内存泄露排查思路

java内存泄露排查思路
Java内存泄露排查思路:
首先,我们需要确认是否存在内存泄露,并明确它的表现特征。
Java内存泄露主要表现在:反复发生OutOfMemoryError异常;性能下降;可用内存大小不断减少;JVM占用的系统内存不断增加。
接下来,我们就可以开始排查相关内存泄露问题了。
1.使用工具检查存在哪些内存泄露问题:Java提供各种工具来帮
助检测和确定是否存在内存泄漏,包括VisualVM、HeapWalker、jmap、jhat等。
2.查看内存分配和使用情况,看哪些对象使用了大量的内存:通
过VisualVM等工具查看内存使用情况,分析哪些对象占用了大量内存,从而确定存在内存泄漏的类。
3.分析内存泄漏的原因:分析存在内存泄漏的类,确定泄漏的原因。
可能的原因有:线程池配置不当;对象不受监控;未正确关闭JDBC资源等。
4.采取措施解决内存泄漏问题:根据内存泄漏的原因,采取措施
解决内存泄漏问题,如:定期回收无用线程;定期检查对象是否受到
监控;正确关闭JDBC资源等。
最后,在解决内存泄漏后,要定期测试程序,以确保解决方案的
正确性。
Java内存泄漏分析系列之一:使用jstack定位线程堆栈信息

Java内存泄漏分析系列之⼀:使⽤jstack定位线程堆栈信息原⽂地址:前⼀段时间上线的系统升级之后,出现了严重的⾼CPU的问题,于是开始了⼀系列的优化处理之中,现在将这个过程做成⼀个系列的⽂章。
基本概念在对Java内存泄漏进⾏分析的时候,需要对jvm运⾏期间的内存占⽤、线程执⾏等情况进⾏记录的dump⽂件,常⽤的主要有thread dump和heap dump。
thread dump 主要记录JVM在某⼀时刻各个线程执⾏的情况,以栈的形式显⽰,是⼀个⽂本⽂件。
通过对thread dump⽂件可以分析出程序的问题出现在什么地⽅,从⽽定位具体的代码然后进⾏修正。
thread dump需要结合占⽤系统资源的线程id进⾏分析才有意义。
heap dump 主要记录了在某⼀时刻JVM堆中对象使⽤的情况,即某个时刻JVM堆的快照,是⼀个⼆进制⽂件,主要⽤于分析哪些对象占⽤了太对的堆空间,从⽽发现导致内存泄漏的对象。
上⾯两种dump⽂件都具有实时性,因此需要在服务器出现问题的时候⽣成,并且多⽣成⼏个⽂件,⽅便进⾏对⽐分析。
下⾯我们先来说⼀下如何⽣成 thread dump。
使⽤⽣成thread dump当服务器出现⾼CPU的时候,⾸先执⾏top -c命令动态显⽰进程及占⽤资源的排⾏,如下图:top后⾯的参数-c可以显⽰进程详细的信息。
top命令执⾏的时候还可以执⾏⼀些快捷键:1对于多核服务器,可以显⽰各个CPU占⽤资源的情况shift+h显⽰所有的线程信息shift+w将当前top命令的设置保存到~/.toprc⽂件中,这样不⽤每次都执⾏快捷键了以上图为例,pid为1503的进程占⽤了⼤量的CPU资源,接下来需要将占⽤CPU最⾼进程中的线程打印出来,可以⽤top -bn1 -H -p <pid>命令,执⾏结果如下:上⾯-bn1参数的含义是只输出⼀次结果,⽽不是显⽰⼀个动态的结果。
我个⼈请喜欢⽤ps -mp <pid> -o THREAD,tid,time | sort -k2r命令查看,后⾯的sort参数根据线程占⽤的cpu⽐例进⾏排序,结果如下:接下来我们清楚今天的主⾓jstack,这是⼀个在JDK5开始提供的内置⼯具,可以打印指定进程中线程运⾏的状态,包括线程数量、是否存在死锁、资源竞争情况和线程的状态等等。
内存泄漏的检测定位和解决经验总结

内存泄漏的检测定位和解决经验总结内存泄漏是指在程序运行过程中,分配的内存一直没有被释放,导致内存的使用量越来越大,最终耗尽系统资源,造成程序崩溃。
内存泄漏是一种常见的程序缺陷,需要及时发现和解决。
一、检测内存泄漏的方法有以下几种:1. 静态代码检查:通过静态代码分析工具进行检查,工具可以扫描代码中的内存分配和释放情况,并发现潜在的内存泄漏问题。
常用的静态代码检查工具包括Coverity、PMD等。
2. 动态代码检查:通过运行时检查工具对程序进行监控,记录内存分配和释放的情况,检查是否有未释放的内存。
常用的动态代码检查工具包括Valgrind、Dr.Memory等。
3. 内存使用分析工具:通过监控程序的内存使用情况,包括内存的分配与释放,内存占用量等信息,来判断是否存在内存泄漏。
常用的内存使用分析工具有Google Performance Tools、Eclipse Memory Analyzer 等。
二、定位内存泄漏的方法有以下几种:1.添加日志:在程序中添加日志跟踪内存的分配与释放情况,当发现内存没有被释放时,通过日志定位问题的位置。
可以通过添加打印语句或者使用专门的日志工具来完成日志记录。
2. 使用内存调试工具:内存调试工具可以跟踪程序中的内存分配和释放情况,并将未被释放的内存标记出来。
通过分析工具提供的报告,可以定位内存泄漏的位置。
常用的内存调试工具有Valgrind、Dr.Memory等。
3. 内存堆栈分析:当程序出现内存泄漏时,通过分析内存堆栈可以得到导致内存泄漏的代码路径。
可以使用工具来进行内存堆栈分析,例如Eclipse Memory Analyzer。
三、解决内存泄漏的方法有以下几种:1. 显式释放内存:在程序中显式地调用释放内存的函数,确保内存被正确地释放。
例如,在使用动态内存分配函数malloc或new分配内存后,必须使用free或delete释放内存。
2. 自动垃圾回收:使用编程语言或框架提供的垃圾回收机制,自动释放不再使用的内存。
内存泄漏排查流程过程和方法

内存泄漏排查流程过程和方法一、内存泄漏的初步判断1.1 观察系统症状当怀疑有内存泄漏时,首先得看看系统的一些表现。
如果系统变得越来越慢,就像蜗牛爬一样,那很可能是内存泄漏捣的鬼。
还有啊,程序运行的时间越长,可用内存就越少,这也是个很明显的信号。
就好比一个水桶有个小漏洞,水一直流出去,桶里的水就越来越少啦。
1.2 查看资源占用情况我们可以查看系统的资源监视器之类的工具。
看看内存的使用量是不是一直往上涨,就像气球不断被吹气一样。
如果内存使用量只增不减,那内存泄漏的可能性就很大了。
二、定位内存泄漏的源头2.1 代码审查这时候就得卷起袖子好好审查代码啦。
看看有没有一些地方在不断地创建对象,但是却没有及时释放。
比如说,有些新手写代码,就像一个马虎的厨师做菜,只知道往锅里加料,却忘记把用过的锅刷干净。
像在循环里不断创建新的对象,却没有在合适的地方销毁,这就是典型的内存泄漏隐患。
2.2 借助工具检测有不少好用的工具能帮我们大忙呢。
像Valgrind这个工具就像是一个侦探,能够嗅出内存泄漏的蛛丝马迹。
它可以详细地告诉我们是哪段代码在搞鬼,就像给我们指出小偷藏在哪里一样。
还有一些编程语言自带的内存分析工具,也非常实用。
2.3 分析内存分配模式我们要仔细分析内存是怎么分配的。
如果发现有一些内存块被分配后,很长时间都没有被再次使用,就像被遗忘在角落里的宝藏一样,那这里就很可能存在内存泄漏。
而且如果大量的小内存块不断被分配,却没有被回收,这也可能是内存泄漏的一种表现形式。
三、解决内存泄漏问题3.1 修复代码逻辑一旦确定了内存泄漏的源头,就要赶紧修复代码逻辑。
如果是对象没有及时释放,那就得在合适的地方加上释放的代码。
这就好比收拾房间,用过的东西要放回原位或者扔掉,不能让它们一直在房间里占地方。
3.2 进行测试验证修复完代码可不能就这么算了,还得进行测试验证。
要确保内存泄漏的问题真的被解决了。
可以长时间运行程序,看看内存使用情况是不是稳定了。
java项目中遇到的问题案例

一、背景介绍在Java项目开发过程中,经常会遇到各种各样的问题,这些问题可能涉及到代码编写、性能优化、技术选型等方方面面。
本文将结合实际项目经验,以案例的形式介绍在Java项目中可能遇到的问题,并对这些问题进行深入分析和解决方案的探讨。
二、问题案例一:内存泄漏问题描述:在一个长期运行的Java应用程序中,发现内存占用逐渐增加,并最终导致了内存溢出。
经过分析发现,在程序运行过程中,存在大量未及时释放的对象占用了大量的内存空间,从而导致了内存泄漏。
解决方案:1. 使用内存分析工具对程序进行分析,定位内存泄漏的具体位置。
2. 检查程序中的代码逻辑,确保对象在不再使用时能够及时被垃圾回收器回收。
3. 使用弱引用、软引用等方式管理对象的生命周期,避免长期占用内存。
三、问题案例二:性能瓶颈问题描述:在一个大型的Java项目中,发现程序在高并发情况下性能急剧下降,响应时间较长,甚至出现了请求超时的情况。
经过分析发现,系统中存在性能瓶颈,导致了系统无法满足高并发请求的需求。
解决方案:1. 使用性能分析工具对程序进行检测,找出性能瓶颈的具体位置。
2. 对程序中的关键模块进行性能优化,例如减少数据库查询次数、优化算法复杂度等。
3. 使用缓存技术对频繁访问的数据进行缓存,减少系统对数据库的访问压力。
四、问题案例三:线程安全问题描述:在多线程并发场景下,程序出现了数据错乱、数据丢失等问题,经过分析发现这是由于程序中存在了线程安全问题导致的。
解决方案:1. 对程序中的共享资源进行合理的加锁保护,确保多线程访问时能够保持数据的一致性。
2. 使用并发控制工具,如Java中的Concurrent包下的工具类来简化线程安全编程的复杂度。
3. 对程序进行多线程并发测试,发现潜在的线程安全问题并及时修复。
五、问题案例四:第三方组件使用问题问题描述:在集成第三方组件时,发现程序出现了各种各样的问题,如兼容性、性能、安全等方面的问题。
解决方案:1. 对第三方组件进行全面的评估和测试,确保其与现有系统的兼容性。
Java开发中的常见错误及其解决方案

Java开发中的常见错误及其解决方案Java是一种跨平台、面向对象、高性能的编程语言,广泛用于Web应用程序开发、移动应用程序开发、游戏开发等方面。
然而,在开发Java应用程序的过程中,常常会出现一些错误和问题,这些问题可能是语法错误、逻辑错误、性能问题等等。
本文将讨论Java开发中的一些常见问题及其解决方案,帮助开发者更好地理解和应对这些问题。
1. 内存泄露内存泄露是一种常见的Java错误。
它指的是程序不必要地占用了内存,但却没有释放。
当一个程序不断运行时,这些未释放的内存会积累,最终导致程序崩溃或变慢。
解决方案:追踪内存泄露的原因并修复它。
可以使用诸如Eclipse Memory Analyzer(MAT)等工具来分析程序内存,找出内存泄漏的原因。
修复内存泄漏通常涉及检查代码中的对象生命周期、确保适当释放资源等。
2. 空指针异常空指针异常是Java程序员最常遇到的问题之一。
它通常是由于访问一个空对象引用而导致的。
这种错误很容易发生,因为程序员可能忘记了为某些对象赋值或在不为空的情况下使用这些对象。
解决方案:添加有效的空对象检查。
程序员应该在使用对象之前检查其是否为空,以避免空指针异常。
可以使用条件语句或对象的非空检查运算符来实现这一点。
3. 类型转换异常类型转换异常通常发生在试图将一个类型转换为不兼容的另一个类型时。
例如,将字符串转换为数字时,如果字符串不是数字,则会发生类型转换异常。
解决方案:使用合适的类型转换方法。
程序员应该使用适当的类型转换方法,例如parseInt方法将字符串转换为整数,以避免类型转换异常。
此外,程序员应该检查数据类型是否兼容,避免尝试将不兼容的数据类型进行转换。
4. 并发问题并发问题是在多个线程同时访问共享数据时发生的问题。
这种情况可能导致数据不一致、死锁、竞争条件等问题。
在Java开发中,常见的并发问题包括线程安全性、死锁、条件竞争等。
解决方案:使用同步措施。
同步措施是指在多个线程中访问共享数据时保持数据一致性的方法。
Java内存泄漏原因分析与解决方案

Java内存泄漏原因分析与解决方案什么是Java内存泄漏?Java内存泄漏是指在Java应用程序中存在某些对象无法被垃圾回收器正确处理而导致内存无法释放的情况。
这种问题会导致程序运行时占用越来越多的内存,最终可能会导致程序出现严重的性能问题甚至崩溃。
Java内存泄漏的原因分析Java内存泄漏可能由多种原因引起,以下是几个常见的原因:1. 长生命周期对象持有短生命周期对象的引用当一个长生命周期的对象持有一个短生命周期对象的引用时,如果该引用没有被适当地释放,短生命周期对象就无法被垃圾回收器回收,从而造成内存泄漏。
这种情况通常发生在使用集合类时,如果在集合中存储了很多对象但没有使用完全,那么这些对象就会一直存在于内存中,无法被释放。
2. 静态引用造成的内存泄漏静态引用是指一个对象被声明为静态变量,这意味着该对象的生命周期与整个应用程序的生命周期相同。
如果静态变量持有其他对象的引用,并且没有正确释放这些引用,就会导致内存泄漏。
这种情况下,即使程序的其他部分已经不再使用某个对象,它也无法被垃圾回收器回收。
3. 未关闭的资源在Java中,一些资源如文件、数据库连接、网络连接等需要手动关闭才能释放内存。
如果程序员忘记关闭这些资源,就会导致内存泄漏。
这种情况下,资源占用的内存会越来越多,最终可能耗尽系统的内存资源。
4. 类加载器泄漏当一个类被加载进内存后,其对应的类加载器也会被加载并保存在内存中,如果类加载器无法被垃圾回收器正确处理,就会导致类加载器本身及其加载的类无法释放,从而造成内存泄漏。
Java内存泄漏的解决方案为了避免Java内存泄漏问题,我们可以采取以下一些解决方案:1. 及时释放不再使用的对象在代码中,应该尽量避免长生命周期对象持有短生命周期对象的引用。
当一个对象不再使用时,应该手动将其引用设置为null,以便垃圾回收器能够正确回收内存。
2. 关闭未使用的资源在使用完资源后,要记得手动关闭它们,例如关闭文件流、数据库连接等。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1. 内网用户500 人,需要同时在线进行业务操作(中午休息一小时,晚6 点下班)。
2. 生产环境采用传统的主从式,未做Cluster ,提供HA 高可用性。
3. 服务器为AIX P570,8U,16G,但是只有一半的资源,即4U,8G 供新系统使用。
项目三月初上线,此前笔者与架构师曾去客户现场简单部署过一两次,主要是软件的安装,应用的部署,测一下应用是不是能够跑起来,时候到了440,系统开始有点反应变慢,不过还是扛下来了,最后归结为目前的资源有限,等把另一半资源划过来,就肯定没问题了。
(须知增加资源,调优的工作大部分都要重新做一遍,系统级、数据库级等等,这也是后面为什么建议如果资源可用,最好一步到位的原因。
)为了临时解决资源有限的问题,通过和客户协商,决定中午12 点半和晚上11 点通过系统调度重启一次应用服务器,这样,就达到了相隔几个小时,手动清理内存的目的。
项目在试运行阶段,仍旧有新的子应用开始投入联调,同时客户每天都会提出这样那样的需求变更,如果要的很急的话,就要随时修改,隔天修正使用。
修改后没有充分的时间进行回归测试,新部署的代码难免会有这样那样的问题,遇到过几次这种情况,最后不得不在业务系统使用的时候,对应用系统进行重新启动,于是就会出现业务终止引起的数据不一致,还要对这些数据进行修正维护,加大了工作量。
期间,应用在运行过程中有几次异常缓慢的情形,由于业务不能中断太久,需要迅速恢复系统投入使用,所以往往是重启一下应用服务器来释放内存。
事后检查日志,才发现日志中赫然记录有OOM 的错误,这才引起了项目经理的注意,要求架构师对该问题进行进一步研究确认。
但是几个月过去,问题依旧出现,于是通过客户和公司的协调,请来几位专家,包括操作系统专家、数据库专家,大部分的专家在巡检之后,给出的结论是:大部分需要调整的参数都已经调整过了,还是要从应用系统本身找原因,看来还是要靠我们自己来解决了。
(最终的结果也证明,如此诡异隐蔽的OOM 问题是很难一眼就能发现的,工具的作用不可忽视。
)我们通过对底层封装的框架代码,主要是DAO 层与数据库交互的统一接口,增加了log 处理以抓取所有执行时间超过10 秒钟的SQ L语句,记录到应用系统日志中备查。
同时通过数据库监控辅助工具给出的建议,对所有超标的SQL 通过建立index,或者修正数据结构(主要是通过建立冗余字段来避免多表关联查询)来进行优化。
这样过了几天后,已经基本上不存在执行时间超过10 秒的SQL 语句,可以说我们对应用层的优化已经达标了。
但是,宕机的问题并没有彻底解决,陆续发生了几次,通过短暂的控制台监控,发现都有线程等待的现象发生,还有两三次产生了几个G 大小的heapdump 文件,同时伴随有javacore 文件产生。
因为每次宕机的时候都需要紧急处理,不允许长时间监控,只能保留应用服务器日志和产生的heapdump 文件,做进一步的研究。
通过日志检查,我们发现几次宕机时都发生在相同的某两个业务点上,但是多次对处理该业务功能的代码进行检查分析,仍旧没有找到原因。
看来只能寄希望于宕机产生的heapdump 和javacore 了,于是开始重点对OOM 产生的这些文件进行分析。
IBM分析工具的使用这里,我们简单介绍一下heapdump 文件和javacore 文件。
heapdump 文件是一种镜像文件,是指定时刻的Java堆栈的快照。
应用程序在发生内存泄露的错误时,往往会生成heapdump 文件,同时伴随有javacore 文件生成,javacore 包含JVM 和应用程序相关的在特定时刻的一些诊断信息,如操作系统,内存,应用程序环境,线程等的信息。
如本文案例中分析的下图中的heapdump.20090602. 134015.430370.phd 和javacore.20090602.134015.430370.txt。
由于笔者之前并没有这方面的分析经验,觉得heapdump 文件很大,就想当然拿它开刀了。
首先是寻找工具,类似的工具有多种,笔者最后选择了IBM 的HeapAnalyzer(/tech/heapanalyzer)。
通过对heapdump 文件的解析,HeapAn alyzer 可以分析出哪些对象占用了太多的堆栈空间,从而发现导致内存泄露或者可能引起内存泄露的对象。
它的使用很简单,可以从它的readme 文档中找到,这里我们简单举个例子如下:#/usr/java50/bin/java – Xmx2000m – jar ha36.jar heapdump.20090602.134015.430370.ph d通常我们需要使用较大的heapsize 来启动HeapAnalyzer,因为通过HeapAnalyzer 打开过大的heapdump 文件时,也可能会因为heapsize 不够而产生OOM 的错误。
开始的时候,笔者从服务器上将heapdump 文件通过ftp 下载下来,然后试图通过本机window 环境进行分析。
笔者使用的电脑是2G 内存,启动HeapAnalyzer 时指定的是1536 M,但是几次都是到90% 多的时候进度条就停止前进了。
迫不得已同时也是为了能达到环境一致的效果,笔者将HeapAnalyzer 上传到生产环境,直接在生产环境下打开heapdump 文件。
个人感觉HeapAnalyzer 给出的分析结果可读性不强,而且不能准确定位问题,从分析结果看大致是因为加载的对象过多,但是是哪个模块导致的问题就跟踪不到了。
笔者开始寻找HeapAnalyzer 分析结果相关的资料,试图从这个可读性不强的结果中找到蛛丝马迹,可是许久没有进展,再一次陷入了困境。
在多次研究heapdump 文件无果的情况下,笔者开始逐渐将注意力转移到javacore 文件上,虽然它比较小,说不定内藏玄机呢。
通过多方搜寻,找到了IBM Thread and Monitor Dump Analyzer for Java(以下简称jca)—— A tool that allows identification of ha ngs, deadlocks, resource contention, and bottlenecks in Java threads。
通过它自身的这段描述来看,这正是笔者所需要的好工具。
这个工具的使用和HeapAnalyzer 一样,非常容易,同样提供了详细的readme 文档,这里也简单举例如下:#/usr/java50/bin/java -Xmx1000m -jar jca37.jar图2. 通过xManager 工具登录到AIX 服务器上打开jca 的效果图笔者直接在生产环境下直接通过它对产生的javacore 文件进行分析,令人惊喜的是,其分析结果非常明了,笔者心头的疑云在对结果进行进一步分析核实后也渐渐散去。
图3. jca 对javacore.20090602.134015.430370.txt 的分析结果——第一部分从图中,我们可以清楚地看到引发错误的原因——The failure was caused because the class loader limit was exceeded。
同时我们还能看出当前生产环境使用的JRE 版本是:J2RE 5.0 IBM J9 2.3 AIX ppc-32 build j9vmap3223-20070201 ,这个SR4 的版本有个问题,我们可以从分析结果图的第二部分的NOTE 小节清楚地看到:图4. jca 对javacore.20090602.134015.430370.txt 的分析结果——第二部分NOTE: Only for Java 5.0 Service Refresh 4 (build date:February 1st, 2007) and older. When you use delegated class loader s, the JVM can create a large number of ClassLoader objects. On IBM Java 5.0 Service Refresh 4 and older, the number o f class loaders that are permitted is limited to 8192 by default and an OutOfMemoryError exception is thrown when this limit is exceeded. Use the -Xmxcl parameter to increase the number of class loaders allowed to avoid this problem, for example to 25000, by setting -Xmxcl25000, until the problem is resolved.原来,OOM 竟然是因为这个原因产生的。
那么到底是哪里加载的对象超过了这个8192 的限制呢?接下来笔者结合分析结果和应用系统log 进行了进一步的分析,更加验证了JCA 分析结果的正确性。
在分析结果中可以看到Current Thread ,就是对应引起OOM 的应用服务器的线程,使用该线程的名称作为关键字在我们的log 里进行搜索,迅速定位到了业务点——这是一个定时的调度,其功能是按固定时间间隔以DBLink 的方式从外部应用的数据库系统中抽取数据,通过应用层逻辑转换后保存到内网数据库系统中。
应用层的逻辑是对所有的业务数据进行循环,对每条业务数据进行到POJO 的一一对照转换,这意味这一条业务数据需要10 几个POJO 进行组合对照,也就是说,如果外网在指定的时间间隔内数据量稍大,就会加载大量的对象,使JVM 的class loaders 瞬间超过8192 的限制,而产生OOM 的错误,从而使内存不断被消耗,直至宕机。
jca 还提供了对垃圾回收和线程状态的详细分析数据,可以参考如下两图:图5. jca 对垃圾回收状态的分析数据图6. jca 对垃圾线程状态的分析数据问题核实后,如何进行解决呢?分析结果中也给出了相应的建议,从图 4 的Recommended 小节我们可以看到:Recommended -Xmxcl setting (only for IBM Java 5.0, up to and including Service Refresh 4 (build date:February 1st ,2007)) : 10,649 or greater。