java内存泄露定位与分析

合集下载

内存泄漏的检测定位和解决经验总结

内存泄漏的检测定位和解决经验总结

内存泄漏的检测定位和解决经验总结内存泄漏是指程序在运行过程中,分配的内存没有被正确释放,导致内存资源无法被再次利用的情况。

由于没有及时释放内存,内存泄漏会导致系统的内存消耗不断增加,最终可能造成程序崩溃或者系统运行缓慢。

解决内存泄漏问题需要进行检测、定位和解决。

一、内存泄漏的检测1. 使用内存分析工具:可以使用一些专门的内存分析工具来检测内存泄漏问题,例如Valgrind、Memcheck等。

这些工具可以跟踪程序运行过程中的内存分配和释放,帮助定位内存泄漏的位置。

2.编写测试用例:通过编写一些针对性的测试用例,模拟程序运行过程中常见的内存分配和释放场景,观察内存的使用情况。

如果发现内存占用持续增长或者没有被及时释放,就可以判断存在内存泄漏问题。

3.监控系统资源:通过监控系统的资源使用情况,如内存占用、CPU使用率等,可以观察系统是否存在内存泄漏的迹象。

如果发现系统的内存占用不断增加,并且没有明显的释放情况,就需要进一步检查是否存在内存泄漏。

二、内存泄漏的定位1.使用日志输出:通过在程序中添加日志输出语句,记录程序运行过程中的重要信息,特别是涉及内存分配和释放的地方。

通过观察日志输出,可以发现是否有内存没有被正确释放的情况。

2.代码分析:通过代码分析,找出可能导致内存泄漏的地方。

常见的内存泄漏问题包括:不恰当的内存分配和释放顺序、不正确的内存释放方式、内存分配大小不匹配等。

对于涉及动态分配内存的地方,要特别关注是否有被遗漏的释放操作。

3.堆栈跟踪:当发现内存泄漏问题比较复杂或者难以定位时,可以使用堆栈跟踪来追踪内存分配和释放的调用路径,找出内存泄漏的具体位置。

在调试过程中,可以通过打印调用栈来获取函数调用的过程,进而确定哪个函数没有正确释放内存。

三、内存泄漏的解决1.及时释放内存:在程序中,所有动态分配的内存都需要及时释放。

对于每个内存分配操作,都要确保相应的释放操作存在,并且在适当的时候进行调用。

java内存泄露排查思路

java内存泄露排查思路

java内存泄露排查思路
Java内存泄露排查思路:
首先,我们需要确认是否存在内存泄露,并明确它的表现特征。

Java内存泄露主要表现在:反复发生OutOfMemoryError异常;性能下降;可用内存大小不断减少;JVM占用的系统内存不断增加。

接下来,我们就可以开始排查相关内存泄露问题了。

1.使用工具检查存在哪些内存泄露问题:Java提供各种工具来帮
助检测和确定是否存在内存泄漏,包括VisualVM、HeapWalker、jmap、jhat等。

2.查看内存分配和使用情况,看哪些对象使用了大量的内存:通
过VisualVM等工具查看内存使用情况,分析哪些对象占用了大量内存,从而确定存在内存泄漏的类。

3.分析内存泄漏的原因:分析存在内存泄漏的类,确定泄漏的原因。

可能的原因有:线程池配置不当;对象不受监控;未正确关闭JDBC资源等。

4.采取措施解决内存泄漏问题:根据内存泄漏的原因,采取措施
解决内存泄漏问题,如:定期回收无用线程;定期检查对象是否受到
监控;正确关闭JDBC资源等。

最后,在解决内存泄漏后,要定期测试程序,以确保解决方案的
正确性。

Java内存泄漏分析系列之一:使用jstack定位线程堆栈信息

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项目中可能遇到的问题,并对这些问题进行深入分析和解决方案的探讨。

二、问题案例一:内存泄漏问题描述:在一个长期运行的Java应用程序中,发现内存占用逐渐增加,并最终导致了内存溢出。

经过分析发现,在程序运行过程中,存在大量未及时释放的对象占用了大量的内存空间,从而导致了内存泄漏。

解决方案:1. 使用内存分析工具对程序进行分析,定位内存泄漏的具体位置。

2. 检查程序中的代码逻辑,确保对象在不再使用时能够及时被垃圾回收器回收。

3. 使用弱引用、软引用等方式管理对象的生命周期,避免长期占用内存。

三、问题案例二:性能瓶颈问题描述:在一个大型的Java项目中,发现程序在高并发情况下性能急剧下降,响应时间较长,甚至出现了请求超时的情况。

经过分析发现,系统中存在性能瓶颈,导致了系统无法满足高并发请求的需求。

解决方案:1. 使用性能分析工具对程序进行检测,找出性能瓶颈的具体位置。

2. 对程序中的关键模块进行性能优化,例如减少数据库查询次数、优化算法复杂度等。

3. 使用缓存技术对频繁访问的数据进行缓存,减少系统对数据库的访问压力。

四、问题案例三:线程安全问题描述:在多线程并发场景下,程序出现了数据错乱、数据丢失等问题,经过分析发现这是由于程序中存在了线程安全问题导致的。

解决方案:1. 对程序中的共享资源进行合理的加锁保护,确保多线程访问时能够保持数据的一致性。

2. 使用并发控制工具,如Java中的Concurrent包下的工具类来简化线程安全编程的复杂度。

3. 对程序进行多线程并发测试,发现潜在的线程安全问题并及时修复。

五、问题案例四:第三方组件使用问题问题描述:在集成第三方组件时,发现程序出现了各种各样的问题,如兼容性、性能、安全等方面的问题。

解决方案:1. 对第三方组件进行全面的评估和测试,确保其与现有系统的兼容性。

Java开发中的常见错误及其解决方案

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内存泄漏的原因分析Java内存泄漏可能由多种原因引起,以下是几个常见的原因:1. 长生命周期对象持有短生命周期对象的引用当一个长生命周期的对象持有一个短生命周期对象的引用时,如果该引用没有被适当地释放,短生命周期对象就无法被垃圾回收器回收,从而造成内存泄漏。

这种情况通常发生在使用集合类时,如果在集合中存储了很多对象但没有使用完全,那么这些对象就会一直存在于内存中,无法被释放。

2. 静态引用造成的内存泄漏静态引用是指一个对象被声明为静态变量,这意味着该对象的生命周期与整个应用程序的生命周期相同。

如果静态变量持有其他对象的引用,并且没有正确释放这些引用,就会导致内存泄漏。

这种情况下,即使程序的其他部分已经不再使用某个对象,它也无法被垃圾回收器回收。

3. 未关闭的资源在Java中,一些资源如文件、数据库连接、网络连接等需要手动关闭才能释放内存。

如果程序员忘记关闭这些资源,就会导致内存泄漏。

这种情况下,资源占用的内存会越来越多,最终可能耗尽系统的内存资源。

4. 类加载器泄漏当一个类被加载进内存后,其对应的类加载器也会被加载并保存在内存中,如果类加载器无法被垃圾回收器正确处理,就会导致类加载器本身及其加载的类无法释放,从而造成内存泄漏。

Java内存泄漏的解决方案为了避免Java内存泄漏问题,我们可以采取以下一些解决方案:1. 及时释放不再使用的对象在代码中,应该尽量避免长生命周期对象持有短生命周期对象的引用。

当一个对象不再使用时,应该手动将其引用设置为null,以便垃圾回收器能够正确回收内存。

2. 关闭未使用的资源在使用完资源后,要记得手动关闭它们,例如关闭文件流、数据库连接等。

java内存泄漏排查思路

java内存泄漏排查思路

java内存泄漏排查思路Java内存泄漏是指程序在运行过程中,无法回收不再使用的内存空间,导致内存占用不断增加,最终耗尽系统内存资源的问题。

内存泄漏会导致程序性能下降、系统崩溃等严重后果,因此及时排查和解决内存泄漏问题是非常重要的。

下面将介绍一些Java内存泄漏排查的思路和方法,帮助开发人员更好地定位和解决内存泄漏问题。

1. 使用内存分析工具:内存分析工具是排查内存泄漏问题的重要利器,常用的工具有Eclipse Memory Analyzer(MAT)、VisualVM、YourKit等。

这些工具可以帮助开发人员分析堆内存中的对象,查看对象的引用关系,定位到可能存在内存泄漏的对象。

2. 分析GC日志:GC日志记录了垃圾回收的过程,可以通过分析GC日志来判断是否存在内存泄漏。

可以使用参数-Xloggc:file将GC日志输出到文件中,然后使用工具(如GCViewer)来分析GC日志,查看堆内存的变化情况和对象的回收情况。

3. 内存泄漏排查工具:除了内存分析工具外,还有一些专门用于排查内存泄漏的工具,如LeakCanary、XRebel等。

这些工具可以自动检测和定位内存泄漏问题,提供可视化的结果展示,简化了排查的过程。

4. 注意弱引用和软引用:Java提供了弱引用(WeakReference)和软引用(SoftReference)来解决内存泄漏的问题。

使用弱引用和软引用可以避免对象被强引用所持有,从而被垃圾回收器回收。

开发人员在编写代码时,应该注意对象引用的强度,避免造成内存泄漏。

5. 关注线程和线程池:线程和线程池是常见的内存泄漏源,因为线程和线程池在使用完毕后需要显式地关闭。

如果没有正确地关闭线程或线程池,会导致线程对象无法被垃圾回收,从而造成内存泄漏。

要注意在使用完毕后及时关闭线程和线程池。

6. 避免静态引用:静态变量会一直存在于内存中,如果静态变量引用了其他对象,那么这些对象也无法被垃圾回收。

Java内存泄露问题分析

Java内存泄露问题分析

Java内存泄露问题分析很多人在谈论内存泄露问题,当然对于c/c++来说,这个应该是老掉牙的问题,但是很多Java人员也越来越多得讨论这个问题,我这里写个小结,希望对大家有一定的参考价值。

内存泄漏的慨念1.c/c++是程序员自己治理内存,Java内存是由GC自动回收的。

我虽然不是很熟悉C++,不过这个应该没有犯常识性错误吧。

2.什么是内存泄露?内存泄露是指系统中存在无法回收的内存,有时候会造成内存不足或系统崩溃。

在C/C++中分配了内存不释放的情况就是内存泄露。

3.Java存在内存泄露我们必须先承认这个,才可以接着讨论。

虽然Java存在内存泄露,但是基本上不用很关心它,非凡是那些对代码本身就不讲究的就更不要去关心这个了。

Java中的内存泄露当然是指:存在无用但是垃圾回收器无法回收的对象。

而且即使有内存泄露问题存在,也不一定会表现出来。

4.Java中参数都是传值的。

对于基本类型,大家基本上没有异议,但是对于引用类型我们也不能有异议。

Java是如何管理内存为了判断Java中是否有内存泄露,我们首先必须了解Java是如何管理内存的。

Java的内存管理就是对象的分配和释放问题。

在Java中,程序员需要通过关键字new为每个对象申请内存空间 (基本类型除外),所有的对象都在堆(Heap)中分配空间。

另外,对象的释放是由GC决定和执行的。

在Java中,内存的分配是由程序完成的,而内存的释放是有GC完成的,这种收支两条线的方法确实简化了程序员的工作。

但同时,它也加重了JVM的工作。

这也是Java程序运行速度较慢的原因之一。

因为,GC为了能够正确释放对象,GC必须监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等,GC都需要进行监控。

监视对象状态是为了更加准确地、及时地释放对象,而释放对象的根本原则就是该对象不再被引用。

为了更好理解GC的工作原理,我们可以将对象考虑为有向图的顶点,将引用关系考虑为图的有向边,有向边从引用者指向被引对象。

Java内存泄露模拟及分析解决方法

Java内存泄露模拟及分析解决方法

e-mail:derwee@ derweeJava内存泄露模拟及分析解决方法1.1 实践目标:1、使用JA V A代码实现模拟内存溢出2、分析JDK内存溢出的原因3、总结存在bug的JA V A编码实践4、总结JVM优化的方法1.2 模拟内存溢出:为了方便模拟内存,特意把JVM的内存参数指定为更小(我的本本内存是8G的)。

修改eclipse参数文件eclipse.ini调用JVM参数:-vmargs-Xms40m(原始是-Xms40m)-Xmx100m(原始是-Xmx384m)演示JA V A小程序实现原理:使用集合类对象装载大量的Persion对象,每次把new出来的对象加入集合类对象后,更改对象的属性,再从集合类对象中删除该对象。

会出现该删除的对象没有被删掉,Persion类对象不断占用内存,导致分配给JVM的内存被耗光。

package com.derwee.collection.memory;import java.util.*;/**** @ClassName: OutOfMemory* @Description: 内存溢出模拟,提出解决方法* @author yangdw* @date 2012-3-25 下午6:58:49*/public class OutOfMemory {public static void main(String[] args){Collection collection = new HashSet();for(int i=0;i<900000000;i++){Persion per = new Persion(i,"yangdw");collection.add(per);//把new出来的对象加到集合里去per.setName("hundsun");//把刚new出来的对象的名字改为 hundsuncollection.remove(per); //把刚加到集合里的对象删除//System.gc();//手工调用垃圾回收器System.out.println("请注意,现在集合对有persion对象数--"+collection.size());}}}package com.derwee.collection.memory;/**** @ClassName: Persion* @Description: TODO(这里用一句话描述这个类的作用)* @author yangdw* @date 2012-3-25 下午8:16:54**/public class Persion {public Persion(int id, String name) {super();this.id = id; = name;}private int id;private String name;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) { = name;}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + id;result = prime * result + ((name == null) ? 0 : name.hashCode());return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;Persion other = (Persion) obj;if (id != other.id)return false;if (name == null) {if ( != null)return false;} else if (!name.equals())return false;return true;}}使用JDK监控程序进行监控JDK内存,线程情况。

内存泄露排查思路

内存泄露排查思路

内存泄漏是指在程序中存在无法访问到的内存块,这些内存块无法被垃圾回收机制回收,最终导致内存的消耗不断增加。

下面是一些内存泄漏排查的思路:1. 使用内存分析工具:使用专门的内存分析工具可以帮助你检测和定位内存泄漏问题。

常见的工具包括Valgrind、LeakCanary、Java VisualVM等。

这些工具可以提供详细的内存使用情况和对象引用关系,帮助你找到潜在的内存泄漏点。

2. 监控内存使用情况:通过监控程序的内存使用情况,可以观察内存的增长趋势和波动情况。

如果内存使用量持续增加,可能是存在内存泄漏。

可以使用操作系统提供的工具或第三方监控工具来监测内存使用情况。

3. 审查代码:仔细审查代码,特别是与内存分配和释放相关的部分。

注意检查以下情况:- 内存分配后未被正确释放。

- 对象被错误地持有引用,导致无法被垃圾回收机制回收。

- 循环引用导致无法回收的对象。

- 缓存对象未正确管理,导致无限制地增长。

- 大对象的创建和使用,可能会导致内存占用过高。

4. 使用日志和调试信息:在关键代码段或内存分配和释放的位置添加日志和调试信息,可以帮助你追踪对象的创建和销毁过程,定位潜在的内存泄漏点。

5. 运行内存压力测试:模拟高负载或长时间运行的场景,观察内存的使用情况。

如果内存占用不断增加,可能存在内存泄漏。

6. 分析垃圾回收日志:某些语言和运行环境提供了垃圾回收日志,可以分析这些日志以了解对象的分配和回收情况。

检查是否有被意外引用或持有的对象,可能是内存泄漏的线索。

7. 进行代码静态分析:使用静态分析工具分析代码,发现潜在的内存泄漏问题。

静态分析工具可以检测出未释放的资源、资源泄漏的风险等问题。

通过结合以上方法,可以帮助你定位和解决内存泄漏问题。

记住,在排查内存泄漏时,耐心和细致是非常重要的,因为内存泄漏可能隐藏在代码的各个角落。

内存泄漏测试与排查方法

内存泄漏测试与排查方法

内存泄漏测试与排查方法内存泄漏是软件开发过程中常见的问题之一,它会导致程序运行变慢、占用过多的系统资源,最终可能引发系统崩溃或应用程序崩溃。

因此,进行内存泄漏测试和排查方法是很重要的。

内存泄漏测试是为了发现应用程序中存在的内存泄漏问题。

下面将介绍一些常用的内存泄漏测试方法。

第一种方法是静态分析。

静态分析是通过检查源代码中可能导致内存泄漏的部分来判断内存泄漏问题。

可以使用静态代码分析工具来辅助进行该项测试。

这些工具可以帮助开发人员发现潜在的内存泄漏问题,如资源未释放、循环引用等。

在测试中,我们可以使用这些工具扫描应用程序的源代码,找出可能存在内存泄漏的地方,并及时修复。

第二种方法是动态分析。

动态分析是通过运行应用程序并监控其内存使用情况来检测内存泄漏。

在这种方法中,我们使用各种性能分析工具来监视应用程序的内存使用情况,例如内存分配和释放的次数、内存泄漏的对象等。

通过分析这些数据,我们可以确定是否存在内存泄漏问题,并找到导致内存泄漏的具体原因。

动态分析是一种非常常用和有效的方法,可以在应用程序运行时发现内存泄漏问题,并及时采取措施进行修复。

第三种方法是使用内存检测工具。

内存检测工具可以帮助开发人员检测内存泄漏问题,并提供详细的报告来指导修复。

这些工具可以监视应用程序运行时的内存分配和释放情况,并检查是否有未释放的内存块。

一旦发现内存泄漏问题,工具会生成相应的报告,指导开发人员进行修复。

常用的内存检测工具包括Valgrind、Memcheck等。

在排查内存泄漏问题时,我们需要注意以下几点。

定位内存泄漏问题。

通过使用上述方法检测和分析应用程序的内存使用情况,确定是否存在内存泄漏问题。

可以通过追踪对象的创建和销毁、监控内存的分配和释放等方法来定位问题。

分析内存泄漏原因。

一旦确定了存在内存泄漏问题,我们需要深入分析其原因。

可能的原因包括资源未正确释放、循环引用等。

修复内存泄漏问题。

根据分析结果,采取相应的措施进行修复。

Java语言内存泄漏定位与避免

Java语言内存泄漏定位与避免

Java语言内存泄漏定位与避免Java语言是一种广泛被使用的编程语言之一,其强大的内存管理功能是开发者青睐的重要原因之一。

然而,像其他编程语言一样,Java语言也存在内存泄漏的问题。

内存泄漏是指在程序执行过程中,本应被回收的内存未能被释放,从而导致系统内存的不断增加,最终引发性能下降甚至系统崩溃的情况。

本文将介绍如何定位和避免Java语言中的内存泄漏问题。

一、Java语言中的内存泄漏Java语言通过垃圾回收(Garbage Collection)机制来自动管理内存,但是如果在代码中存在一些潜在问题,就有可能导致内存泄漏的发生。

下面列举了几种常见的Java内存泄漏情况:1. 对象的引用未及时释放:当一个对象的引用被赋给一个变量后,如果这个对象在执行过程中再也没有被引用到,但是没有显式地将其置为null,那么该对象就无法被垃圾回收机制回收,造成内存泄漏。

2. 集合类未正确使用:在使用集合类(如ArrayList、HashMap等)时,如果没有在适当的时候清除不再使用的元素或者没有调用集合的clear()方法,就有可能导致内存泄漏。

3. 静态集合类的使用不当:静态集合类的对象被所有类共享,如果在使用完后没有及时清空,那么对象中的元素将一直被引用,无法被回收,造成内存泄漏。

4. 资源未关闭:在操作一些资源对象(如文件、数据库连接等)时,如果没有适时关闭这些资源,将导致资源对象一直被引用,从而无法释放内存。

二、定位Java语言中的内存泄漏问题定位Java语言中的内存泄漏问题是解决该问题的第一步,下面介绍几个常用的方法。

1. 使用内存监控工具:Java提供了一些内存监控工具,如VisualVM、jconsole等,通过这些工具可以查看内存使用情况、垃圾回收情况,从而定位可能存在的内存泄漏问题。

2. 代码审查:仔细审查代码,找出可能存在内存泄漏的地方。

特别需要注意的是,查找是否有忘记释放资源、是否有未清理集合的情况。

有效解决Java中常见的内存泄漏问题

有效解决Java中常见的内存泄漏问题

有效解决Java中常见的内存泄漏问题在Java编程中,内存泄漏是一个常见的问题。

这种情况会导致系统内存不断增长并最终导致应用程序的崩溃。

在这篇文章中,我们将讨论如何避免和处理Java中的内存泄漏问题。

一、什么是内存泄漏?内存泄漏指在软件程序中,由于程序员的疏忽、失误或程序设计的不合理等原因,导致在运行过程中分配的内存空间没有被有效地释放,使得一些可用的内存暂时或永久地无法被程序使用,导致系统内存的不断增加。

如果内存泄漏得不到及时的修复,则可能会导致系统崩溃。

二、Java中的内存泄漏在Java中,内存泄漏通常是由于程序员在某些情况下没能正确的释放其不再需要的对象所导致的。

Java有自动的垃圾回收机制,这使得内存泄漏可能不再像C++那样危险,但是程序员仍然需要注意对象管理。

下面是Java中常见的几种内存泄漏的情况:1. 长生命周期的对象持有短生命周期的对象的引用在Java中,短生命周期的对象比如线程、事件和定时器等通常比较小,而长生命周期的对象比如GUI组件、数据库连接等通常比较大。

如果这些长生命周期对象保持对短生命周期对象的引用,那么这些短生命周期对象就不能被垃圾回收,从而导致内存泄漏。

2. 静态变量引用对象当一个类的静态变量引用一个对象时,这个对象将会在应用程序运行的整个生命周期内一直存在。

如果这个对象不再需要,但是静态变量仍在引用它,那么这个对象就无法被垃圾回收,从而导致内存泄漏。

3. 软引用和弱引用的不正确使用在Java中,可以使用软引用或弱引用保留对象引用。

这些引用可以帮助开发人员编写高效的程序,但是如果不正确使用,也会导致内存泄漏。

软引用和弱引用只有在被访问时才能保持引用,但是如果一个对象不再被访问,同时又被软引用或弱引用保留,那么这个对象将会被认为是垃圾而被回收。

三、避免内存泄漏的方法1. 及时释放资源程序员应该及时地释放他们分配的资源,特别是一些明确需要关闭的资源,如文件和数据库连接。

掌握Java中的内存泄漏检测与优化

掌握Java中的内存泄漏检测与优化

掌握Java中的内存泄漏检测与优化Java是一种面向对象的编程语言,其通过自动内存管理机制,即垃圾回收机制,来自动管理内存分配和释放。

然而,即使在这种自动内存管理机制下,仍然存在内存泄漏的问题。

内存泄漏指的是在程序运行过程中,不再需要的内存没有被及时释放,造成内存资源的浪费。

本文将详细介绍Java中内存泄漏的概念、检测和优化方法。

一、内存泄漏的概念内存在Java中是通过new操作符来分配的,当一个对象不再被使用时,应该及时将其释放以便重新利用该内存空间。

然而,如果在程序中存在某些对象无法被垃圾回收机制释放的情况,就会导致内存泄漏。

常见的内存泄漏场景包括:1.长生命周期的对象持有短生命周期对象的引用:如果一个长生命周期的对象持有一个短生命周期对象的引用,并且在长生命周期对象不再使用时忘记了释放这个引用,就会导致内存泄漏。

2.静态变量持有对象的引用:如果一个对象被赋值给一个静态变量,并且在这个对象不再需要时没有将该引用置空,就会导致内存泄漏。

3.监听器、回调函数等资源没有正确释放:如果一个对象注册了某个监听器或回调函数,但在对象不再需要时忘记了注销该监听器或回调函数,就会导致内存泄漏。

4.缓存导致的内存泄漏:如果对一个大量的对象进行缓存,但在不再需要这些对象时没有清理缓存,就会导致内存泄漏。

5.循环引用:如果两个或多个对象之间形成了循环引用,并且这些对象都没有被其他对象引用,就会导致内存泄漏。

二、内存泄漏的检测方法1.内存泄漏分析工具:Java提供了一些用于检测内存泄漏的工具,例如JVisualVM、YourKit等。

这些工具可以通过分析堆内存中的对象引用关系,帮助我们查找可能存在的内存泄漏问题。

2.日志分析:通过分析应用程序的日志,查看是否存在内存占用过高的情况,以及内存占用是否随时间增长。

三、内存泄漏的优化方法1.及时释放资源:当一个对象不再需要时,应该及时将其引用置空,以便垃圾回收机制能够释放其占用的内存空间。

解决JAVA内存泄漏问题的策略

解决JAVA内存泄漏问题的策略

解决JAVA内存泄漏问题的策略引言:在开发和维护JAVA应用程序时,经常会遇到内存泄漏问题。

内存泄漏是指在程序运行过程中,分配的内存空间没有被正确释放,导致内存占用不断增加,最终导致程序崩溃或性能下降。

本文将介绍一些解决JAVA内存泄漏问题的策略,帮助开发人员更好地应对这一挑战。

一、了解内存泄漏的原因内存泄漏的原因有很多,常见的包括:1. 对象的生命周期管理不当:在JAVA中,对象的生命周期由垃圾回收器(Garbage Collector)来管理。

如果开发人员没有正确地释放不再使用的对象,这些对象将一直存在于内存中,导致内存泄漏。

2. 静态引用:静态变量和静态集合类常常是内存泄漏的罪魁祸首。

因为静态变量在整个程序的生命周期中都存在,并且可以被其他对象直接引用,如果不及时释放,就会导致内存泄漏。

3. 未关闭的资源:在使用一些需要手动关闭的资源(如文件、数据库连接等)时,如果开发人员忘记关闭这些资源,就会导致内存泄漏。

4. 循环引用:当两个或多个对象之间相互引用,并且没有外部对象引用它们时,就会形成循环引用。

这种情况下,垃圾回收器无法判断这些对象是否还有被引用的必要,从而导致内存泄漏。

二、解决内存泄漏问题的策略为了解决内存泄漏问题,开发人员可以采取以下策略:1. 使用合适的数据结构和算法:在设计和实现程序时,应选择合适的数据结构和算法,以减少内存占用。

例如,对于大量数据的处理,可以使用迭代器模式或分页查询等方式,避免一次性加载全部数据到内存中。

2. 及时释放资源:在使用完资源后,应该及时关闭或释放它们,以避免资源的持久化占用内存。

对于需要手动关闭的资源,可以使用try-finally或try-with-resources等语法糖来确保资源的正确关闭。

3. 避免使用静态引用:尽量避免使用静态变量和静态集合类,特别是在不需要全局共享状态的情况下。

如果确实需要使用静态引用,应该及时释放这些引用。

4. 注意对象的生命周期:在编写代码时,应该清楚对象的生命周期,并在不再使用时及时将其置为null。

java内存泄露定位与分析

java内存泄露定位与分析

1. 内网用户500 人,需要同时在线进行业务操作(中午休息一小时,晚6 点下班)。

2. 生产环境采用传统的主从式,未做Cluster ,提供HA 高可用性。

3. 服务器为AIX P570,8U,16G,但是只有一半的资源,即4U,8G 供新系统使用。

项目三月初上线,此前笔者与架构师曾去客户现场简单部署过一两次,主要是软件的安装,应用的部署,测一下应用是不是能够跑起来,时候到了440,系统开始有点反应变慢,不过还是扛下来了,最后归结为目前的资源有限,等把另一半资源划过来,就肯定没问题了。

(须知增加资源,调优的工作大部分都要重新做一遍,系统级、数据库级等等,这也是后面为什么建议如果资源可用,最好一步到位的原因。

)为了临时解决资源有限的问题,通过和客户协商,决定中午12 点半和晚上11 点通过系统调度重启一次应用服务器,这样,就达到了相隔几个小时,手动清理内存的目的。

项目在试运行阶段,仍旧有新的子应用开始投入联调,同时客户每天都会提出这样那样的需求变更,如果要的很急的话,就要随时修改,隔天修正使用。

修改后没有充分的时间进行回归测试,新部署的代码难免会有这样那样的问题,遇到过几次这种情况,最后不得不在业务系统使用的时候,对应用系统进行重新启动,于是就会出现业务终止引起的数据不一致,还要对这些数据进行修正维护,加大了工作量。

期间,应用在运行过程中有几次异常缓慢的情形,由于业务不能中断太久,需要迅速恢复系统投入使用,所以往往是重启一下应用服务器来释放内存。

事后检查日志,才发现日志中赫然记录有OOM 的错误,这才引起了项目经理的注意,要求架构师对该问题进行进一步研究确认。

但是几个月过去,问题依旧出现,于是通过客户和公司的协调,请来几位专家,包括操作系统专家、数据库专家,大部分的专家在巡检之后,给出的结论是:大部分需要调整的参数都已经调整过了,还是要从应用系统本身找原因,看来还是要靠我们自己来解决了。

(最终的结果也证明,如此诡异隐蔽的OOM 问题是很难一眼就能发现的,工具的作用不可忽视。

JAVA内存泄露分析及解决

JAVA内存泄露分析及解决

JAVA内存泄露分析及解决⼀,问题产⽣项⽬采⽤Tomcat6.0为服务器,数据库为mysql5.1,数据库持久层为hibernate3.0,以springMVC3.0为框架,项⽬开发完成后,上线前⼣进⾏稳定性拷机,测试数据为插⼊4条/S,更新4条/S,访问300次/S,前期运⾏速度顺畅,三天后就开始运⾏缓慢,访问量达到1500W次后以抛出Java heap space结束.⼆.问题分析1.前期分析为连接池内存溢出,期间优化了连接池参数,调整了tomcat线程参数,替换数据库连接池,问题依旧2.看来问题不是简单的参数配置,需要进⾏⼀点深⼊的研究分析了,在和同事研究了⼀些资料后,对JAVA的垃圾收集机制有了⼀定的了解,JVM的内存模型分为新⽣代和⽼⽣代,JDK本⾝提供了⼀个监视⼯具jconsole.exe,进⼊bin⽂件夹打开后,选择连接--tomcat--内存,可以开始监视JVM内存回收情况,通过⼀段时间的监视后,发现了⽼⽣代的内存回收存在异常.从上图可以看出,每次回收的内存都⽐上⼀次少,可以判断⽼⽣代的内存发⽣了泄露.3.虽然知道了存在内存泄露,但是⽆法判断是哪⾥发⽣了泄露,为此我们需要把堆(dump)导出来进⾏分析,JDK也提供了导出⼯具jvisualvm.exe,启动后右键点击线程--堆Dump,可以导出Dump⽂件.4.使⽤MAT(MemoryAnalyzer)分析Dump⽂件,该⼯具的下载地址为:,可以下载离线版,也可以集成到eclipse,使⽤很⽅便.打开该⼯具导⼊Dump⽂件,稍等⼀会,就可以得出MAT提供的分析报告MAT指出了该Dump中⼀个HashMap的实例发⽣了内存泄露,占⽤了JVM819M的内存,继续点击Details可以得到更详细的信息这个detail⽐较详细的指出了问题所在,⼀个叫viewCache的hashMap实例占⽤共859M内存,虽然每个实例只有⼏百字节,但是⼀共产⽣了134W个实例.5.分析出这个问题点,接下去就是排查代码问题了,排查代码得知该项⽬使⽤springMVC,其中viewCache是spring中使⽤的⼀个视图缓存,在项⽬中如⼀个处理视图跳转的代码:LinkedList list = this.getPathParam(mvValue);for (int i = 0; i < list.size(); i++) {String paramName = (String) list.get(i);String paramValue = null;paramValue = RequestUtils.getParamString(map, paramName);paramValue = paramValue == null ? "" : paramValue;mvValue = StringUtils.replace(mvValue, "#" + paramName+"#", paramValue);}return new ModelAndView(mvValue);由于paramValue每次都是动态⽣成的uuid,造成了每次的mvvalue都不同,这样每次都会⽣成⼀个不⼀样的视图,这样的视图累积到100多W个的时候,终于把tomcat撑暴了.百度了⼀下,果然也已经有⼈注意到了这个问题:.6.知道了问题所在后,就可以修改代码了,我们需要将ModelAndView的视图名称固定,动态参数可以通过ModelAndView提供的addObject⽅法传⼊,修改后的代码如下://判断如果视图名称包含"snms_result.jsp",则将视图名称返回值统⼀,解决因动态产⽣视图名称过多产⽣的内存泄露问题, by feitianbubu 2013年5⽉27⽇ 11:21:31ModelAndView mv=new ModelAndView(mvValue);LinkedList list = this.getPathParam(mvValue);for (int i = 0; i < list.size(); i++) {String paramName = (String) list.get(i);String paramValue = null;paramValue = RequestUtils.getParamString(map, paramName);paramValue = paramValue == null ? "" : paramValue;mv.addObject("id", ",'"+paramValue+"'");}return mv;7. 代码commit SVN,发布拷机,观察内存回收情况(为了更快模拟环境采⽤1000次/S插⼊数据和1000次/S读取数据,所以GC会⽐较频繁)可以看出⽼⽣代内存得到有效回收,内存泄露的问题得到解决。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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。

相关文档
最新文档