自己最近做了一些关于工厂MES软件导致的OOM,比如avon,andersen,ford, 这是给公司同事做的OutOfMemory定位问题的分享,垃圾回收是参考江南白衣的一篇博文,各个点都是些比较表层的sharing,还没有写完,也和广大同仁做个交流
1 分析工具
1) 动态分析工具
Jprofile
2) 静态分析工具
a: 在启动java的时候加上参数 -XX:+HeapDumpOnOutOfMemoryError,这样如果由于OOM导致JVM crash的时候可以便于我们分析,生成的heap dump文件名字的命名规范如下, java_pidxxxx.hprof
b: 工具1 elcipsemat
2 IBM heap ana java -Xmx1600 -jar ha396.jar
2 Java 内存机制和Exception实例
1对于从事C、C++程序开发的开发人员来说,担负着每一个对象生命开始到终结的维护责任。
对于Java程序员来说,不需要在为每一个new操作去写配对的delete/free,不容易出现内容泄漏和内存溢出错误。不过,也正是因为Java程序员把内存控制的权力交给了JVM,一旦出现泄漏和溢出,如果不了解JVM是怎样使用内存的,那排查错误将会是一件非常困难的事情。下面介绍一下java出现的OOM有关的 Exception和可能出现的方式
A Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
public static void main(String[] args) {
//使用List保持着常量池引用,压制Full GC回收常量池行为
List<String> list = new ArrayList<String>();
// 10M的PermSize在integer范围内足够产生OOM了
int i = 0;
while (true) {
list.add(String.valueOf(i++).intern());
}
}
这一部分用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域(包括常量池: 静态变量),它和和存放Instance的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误动态生成的类,加载如Spring、Hibernate对类进行增强时,都会使用到CGLib这类字节码技术,当增强的类越多,就需要越大的方法区用于保证动态生成的Class可以加载入内存。
B java.lang.OutOfMemoryError: Java heap space,被缓存的实例(Cache)对象,大的map,list引用大的对象等等,都会保存于此
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
int i = 0;
while (true) {
list.add(new String(“test”));
}
}
C Exception in thread "main" java.lang.StackOverflowError
栈帧太多,也就是函数调用层级过多)导致。检查是否有死递归的情况~
/**
* VM Args:-Xss128k
*/
public class JavaVMStackSOF {
private int stackLength = 1;
public void stackLeak() {
stackLength++;
stackLeak();
}
public static void main(String[] args) throws Throwable {
JavaVMStackSOF oom = new JavaVMStackSOF();
try {
oom.stackLeak();
} catch (Throwable e) {
System.out.println("stack length:" + oom.stackLength);
throw e;
}
}
}
2 Java 垃圾回收机制
基本回收算法
-
引用计数(Reference Counting)
比较古老的回收算法。原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数。垃圾回收时,只用收集计数为0的对象。此算法最致命的是无法处理循环引用的问题。
-
标记-清除(Mark-Sweep)
此算法执行分两阶段。第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除。此算法需要暂停整个应用,同时,会产生内存碎片。
-
复制(Copying)
此算法把内存空间划为两个相等的区域,每次只使用其中一个区域。垃圾回收时,遍历当前使用区域,把正在使用中的对象复制到另外一个区域中。次算法每次只处理正在使用中的对象,因此复制成本比较小,同时复制过去以后还能进行相应的内存整理,不会出现“碎片”问题。当然,此算法的缺点也是很明显的,就是需要两倍内存空间。
-
标记-整理(Mark-Compact)
此算法结合了“标记-清除”和“复制”两个算法的优点。也是分两阶段,第一阶段从根节点开始标记所有被引用对象,第二阶段遍历整个堆,把清除未标记对象并且把存活对象“压缩”到堆的其中一块,按顺序排放。此算法避免了“标记-清除”的碎片问题,同时也避免了“复制”算法的空间问题。
-
分代(Generational Collecting)
基于对对象生命周期分析后得出的垃圾回收算法。把对象分为年青代、年老代、持久代,对不同生命周期的对象使用不同的算法(上述方式中的一个)进行回收。现在的垃圾回收器(从J2SE1.2开始)都是使用此算法的。
分代垃圾回收详述
如上图所示,为Java堆中的各代分布。
-
Young(年轻代)
年轻代分三个区。一个Eden区,两个Survivor区。大部分对象在Eden区中生成。当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor去也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制“年老区(Tenured)”。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来 对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor去过来的对象。而且,Survivor区总有一个是空的。
-
Tenured(年老代)
年老代存放从年轻代存活的对象。一般来说年老代存放的都是生命期较长的对象。
-
Perm(持久代)
用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,例如Hibernate等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过-XX:MaxPermSize=<N>进行设置。
-
能导致Full GC:
-
Tenured被写满
-
Perm域被写满
-
System.gc()被显示调用
-
上一次GC之后Heap的各域分配策略动态变化
3实战演练
背景介绍
1这个是Andersen window 的一个Support Case,他们用我们FTPC的Form开发了一个从ERP系统导入WorkOrder等到我们FTPC系统的一个转换程序,他们把ERP系统的所有Order写到一个txt文件里面,然后用他们的写的应用来转换txt中的Order信息到我们FTPC的Lot, workorder对象等等。但是他们发现有个问题,就是导入的txt文件如果过大的话,就会有可能报出OOM异常,这个对他们影响是很大的,他们不知道当前导入了多少order,没法回滚脏数据。于是Support建议他们加大Client端的内存,但是这样还是会有问题的,因为你不知道从ERP导出的txt的文件有多大。
2
这里可以让大家猜测大概是什么问题导致的内存泄露
这个是用 IBM heap ana分析的视图,大家可以看一下,有96%内存都在pnuts/lang/context中,其中92%内存是被lot对象占用的,lot对象保存到Vector中,所以是由于lot对象保存在Vector中,但是vector没有及时释放这些对象导致的。
3实际内存泄露的代码.
Please locate the lines of code around line 2736 of Subroutine ImportWoFile. Following is the some pieces of the codes about it:
foreach orderItem(vecOrderItems.elements())
{
….
newLot = createLot(strLotName, workOrder)
…
newLot.save()
…
if (blnSaveOK == false)
{
……
} else
{
//vectLot is a Vector collection customer defined newly on 10/10/2010
vecLot.addElement(newLot)
….
}
}
My conclusion:Obviously, the lot of vectLot will be tremendous if they want to import a large wo file at one time. So it will consume the memory of JVM.
分享到:
相关推荐
最近在跑程序,然后Pycharm就跳出out of memory 的错误提示,可能是由于读取的数据太多导致的,Pycharm有一个默认内存的最大容量上线,跳出提示的是1024M,也就是分配给Pycharm的内内存不够啦! 一、说明: pycharm...
解决Out of memory问题,玩游戏的童鞋遇到的问题,希望能帮到那些遇到此类问题的童鞋
- **查看错误日志**:Tomcat的`catalina.out`日志会记录`Out of Memory`错误的具体信息,帮助定位问题。 - **使用JConsole或JVisualVM**:这些JDK自带的工具可以实时监控JVM的内存使用情况,辅助诊断。 - **分析...
在IT行业中,"APE(flex out of memory)"这个问题通常是与Adobe Flex开发相关的内存溢出问题。Flex是一种开源的、基于MXML和ActionScript的框架,用于构建富互联网应用程序(RIA)。当你遇到“Out of memory-cannot ...
"Out of memory" 是一个常见的计算机错误提示,通常在运行程序或系统操作时出现,意味着计算机没有足够的内存(RAM)来执行请求的操作。这可能是由于多个原因造成的,包括但不限于资源管理不当、内存泄漏、大型数据...
一次奇怪的Out of Memory 分析(附图)
标题 "BlazeDS+Spring+activeMQ outofmemory" 指的是在使用BlazeDS、Spring和ActiveMQ集成的环境中遇到了内存溢出问题。BlazeDS是一个开放源码的服务器端技术,它允许双向通信,使Flex或AJAX客户端能够与Java后端...
标题 "使用Memory Analyzer tool检测OutofMemory异常" 涉及到的是Java内存管理的一个重要环节,即如何通过工具分析并解决程序运行时出现的内存溢出问题。Memory Analyzer Tool (MAT) 是由Eclipse基金会开发的一款...
1. **定位配置文件**:首先,需要找到Tomcat安装目录下的`bin`文件夹,该文件夹中包含了用于启动和停止Tomcat服务的脚本文件。 2. **编辑`catalina.sh`脚本**:在`catalina.sh`脚本的开头位置,加入以下行来设置JVM...
然而,在训练深度学习模型时,我们经常遇到“CUDA error: out of memory”这样的错误,这表明GPU的显存不足以运行当前的任务。本文将详细介绍这个问题的原因、影响以及解决方法。 ### 问题原因 1. **模型复杂度过...
标题与描述中的关键词“Tomcat Out of Memory Solution”指向了在运行Tomcat服务器时遇到内存溢出错误(Out of Memory Error)的解决方法。在IT领域,尤其是Java应用服务器环境中,Tomcat作为一款广泛使用的开源轻量...
本文将深入探讨Python运行文件时出现“out of memory”错误的原因、解决策略以及如何优化内存使用。 首先,我们要理解Python内存管理的基本原理。Python采用自动内存管理,包括垃圾回收机制,它会自动回收不再使用...
Git是世界上最流行的分布式版本控制系统,但在使用过程中可能会遇到各种问题,其中之一就是"Out of memory"错误。这个错误通常发生在执行诸如`git clone`这样的大型操作时,当Git尝试分配大量内存来处理数据时,如果...
"Out of Memory"是计算机操作系统中常见的一个错误提示,意味着系统在执行某个程序或操作时,没有足够的内存资源可供分配。这通常是由于以下几个原因引起的: 1. **运行的程序占用内存过大**:某些大型应用程序,如...
Out of Memory(处理方案).md
Out of Memory(解决方案).md
在使用PyTorch进行深度学习模型训练时,有时会遇到一个常见的问题,即GPU显存充足,但在运行过程中却报出“out of memory”错误。这种情况可能会让人困惑,因为直观上,既然显存足够,就不应该出现这样的问题。本文...