`
zhuyufufu
  • 浏览: 137286 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Java内存溢出问题的定位过程

阅读更多
相信通过写java程序讨生活的人对内存溢出并不陌生,如下文字的出现更是让人恼火:
java.lang.OutOfMemoryError: Java heap space
java.lang.OutOfMemoryError: PermGen space
尤其当应用服务器(Java容器)出现上述情况更是让人有一种天塌下来的感觉。

   好的编码实践可能会大大降低内存溢出的产生。
   本文并不是写如何规避内存溢出,但是我还是要介绍一下如何能够尽量规避内存溢出:
   1. 编码规范认真执行。找几个资深程序猿(或者整个项目组讨论后)写一个Java编码规范,让项目组成员尽量遵守。一目了然的代码更容易定位问题,当然也更能让人写出好的代码。
   2. 单元测试要覆盖所有分支与边界条件。不要拿某种情况不会出现做借口。有句老话说常在河边站哪有不湿鞋(学名墨菲定律)。
   3. 代码审查要走。代码写完了,找资深程序猿扫扫代码没有坏处。
   4. 有条件的项目组要充分利用测试人员的能动性。
   5. 如果项目的期望较高,就把上面的尽量、可能等词汇改成一定要。

   以上五条建议对非性命攸关型项目足够了。





下面说正题:

   对于java.lang.OutOfMemoryError: PermGen space 这种情况更多的是靠程序猿的经验来解决:

   PermGen space的全称是Permanent Generation space,是指内存的永久保存区域, 这块内存主要是被JVM存放Class和Meta信息的,Class在被Load时就会被放到PermGen space中, 它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对 PermGen space进行清理,所以如果你的应用中有很多CLASS的话,就很可能出现PermGen space错误。

   通过上面的描述就可以得出:如果要加载的class与jar文件大小超过-XX:MaxPermSize就有可能会产生java.lang.OutOfMemoryError: PermGen space 。

   换句话说-XX:MaxPermSize的大小要超过class与jar的大小。通常-XX:MaxPermSize为-Xmx的1/8。

  

   对于java.lang.OutOfMemoryError: Java heap space 可能定位的过程就需要折腾一翻了:

   虽然各种java虚拟机的实现机制不一,但是heap space内存溢出产生的原因相同:那就是堆内存不够虚拟机分配了。

   我对java虚拟机的实现不感兴趣,对各种虚拟机的内存分配机制与gc的交互关系也不了解。但是我大致认为内存分配机制与gc是有联系的,也就是说内存不够分配时gc肯定也释放不了堆内存。从这一点出发,我们就需要找为什么gc释放不了堆内存。通常来说释放不了是因为内存还在使用。对于java对象产生的堆内存占用,只要其不再被继续引用gc是能够顺利回收的(对于通过本地方法调用,即JNI调用产生内存泄露的情况暂不考虑)。

   问题的关键就找到了,当产生heap space内存溢出时,堆内存中对象数量过多的就可能是问题的根源了。例外的情况是,程序确实需要那么多内存,这时就要考虑增大堆内存。

   例外的情况在本文中就不再多说了,下面介绍jdk自带的两个可视化工具来定位问题。

jdk/bin/jconsole.exe  jdk/bin/jvisualvm.exe
  
   jconsole.exe可以查看本地以及远程主机上的java虚拟机的当前状况,这对服务器健康检查情况非常有用。如下图:



   jvisualvm.exe可以用来查看分析内存转储文件;也可以用其做java虚拟机当前状况查看,但是jvisualvm.exe的侵入性非常强,一旦使用会严重影响应用性能。如下图:



  下面写些代码来演示一下内存溢出的产生,堆转储文件的生成,堆内存的分析。
 
  首先创建数据持有对象类:
package com.zas.jvm.om;

/**
 * 数据对象
 * @author zas
 */
public class DataObject {
	//数据对象ID
	private String id;
	//数据对象内容
	private String des;
	
	public DataObject(String id, String des) {
		super();
		this.id = id;
		this.des = des;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getDes() {
		return des;
	}

	public void setDes(String des) {
		this.des = des;
	}

	@Override
	public String toString() {
		return "DataObject [id=" + id + ", des=" + des + "]";
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {

	}

}


溢出演示代码
package com.zas.jvm.om;

import java.util.ArrayList;
import java.util.List;

public class OutMemeryTest {
	
	List<DataObject> list = new ArrayList<DataObject>();
	
	public void testOm(){
		for (int i = 0; i < 100000; i++) {
			DataObject data = new DataObject("id&"+i, "des:"+i);
			list.add(data);
		}
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		OutMemeryTest omt = new OutMemeryTest();
		for (int i = 0; i < 2; i++) {
			omt.testOm();
		}
		System.out.println("DOne!");
		try {
			Thread.sleep(100000000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}



运行参数设置如下:-Xms64m -Xmx64m -XX:PermSize=8m -XX:MaxPermSize=8m
-XX:-HeapDumpOnOutOfMemoryError          
见下图:




jvisualvm分析效果图:
  

从上图结合代码明显得出:com.zas.jvm.om.DataObject这个类的对象出了问题。


以上是一个演示问题产生及定位过程,生产环境的问题千奇百怪需要具体问题具体分析。

当堆内存巨大时可能要调整jdk\lib\visualvm\etc\visualvm.conf文件中的-xms -xmx大小来导入转储文件。

生产环境为linux的较多,可以借助jdk自带的jmap来转储堆内存文件来分析。
0
0
分享到:
评论

相关推荐

    JVM内存溢出问题解析

    JVM 内存溢出问题解析 JVM 内存溢出是指程序运行所需的内存大于虚拟机能提供的最大内存的情况。这种情况可能是由于数据量过大、死循环、静态变量和静态方法过多、递归、无法确定是否被引用的对象等原因引起的。同时...

    Java内存溢出解决办法

    Java内存溢出问题,全称为Java OutOfMemoryError,是Java开发者经常遇到的运行时异常。...了解和掌握这些知识点,可以帮助开发者在遇到Java内存溢出问题时迅速定位并解决,确保应用的稳定性和效率。

    java内存泄露、溢出检查方法和工具

    总的来说,Java内存管理和诊断是一个复杂的过程,需要深入理解JVM的工作原理和垃圾收集机制。通过合理使用各种工具和技巧,开发者能够有效地识别和解决内存泄露和溢出问题,确保应用程序的稳定性和性能。

    java 内存溢出分析工具 HeapAnalyzer

    Java内存溢出(Out of Memory,OOM)是Java应用程序中常见的问题,会导致程序崩溃或性能急剧下降。HeapAnalyzer是一款强大的工具,专为分析Java应用程序的内存状况,特别是针对内存溢出问题进行诊断。本文将详细介绍...

    java内存溢出解决方案

    Java内存溢出问题通常指的是Java应用程序在运行过程中由于内存分配不当或使用过度导致JVM无法分配更多的内存,从而抛出`java.lang.OutOfMemoryError`异常。本文将深入探讨Java内存溢出的不同类型及其解决方案。 1. ...

    Java内存溢出问题

    Java内存溢出问题,是Java开发中常见的性能问题,它发生在程序运行时,由于系统无法分配足够的内存资源来满足程序的运行需求,导致程序异常终止。深入理解Java内存溢出,有助于我们优化程序,提高系统稳定性。下面...

    java内存溢出原因

    Java内存溢出(Out Of Memory, OOM)是开发者在编程过程中经常遇到的问题,尤其是在处理大量数据或长时间运行的应用程序时。本篇文章将详细解析三种常见的Java内存溢出类型:JVM PermGen space溢出、JVM heap space...

    基于HeapAnalyzer456.jar 分析java内存溢出

    本篇文章将详细介绍如何使用HeapAnalyzer456.jar来分析Java内存溢出问题。 首先,我们需要了解内存溢出的基本概念。Java内存分为堆内存(Heap)和非堆内存(Non-Heap),其中堆内存主要存储对象实例,当程序创建...

    内存溢出解决

    #### 解决Java内存溢出的方法 ##### 1. **理解内存结构** 在深入探讨解决方案之前,首先需要了解Java虚拟机(JVM)的内存布局: - **堆内存**:存放对象实例和数组。 - **栈内存**:线程私有的,用于存储局部变量...

    java 内存溢出分析工具 CoreAnalyzer

    Java内存溢出(Out of Memory, OOM)是开发者在编程过程中经常遇到的问题,尤其是在处理大量数据或长时间运行的应用程序时。为了解决这一问题,Java提供了多种内存分析工具,其中CoreAnalyzer是一款专业的Java内存...

    Java内存溢出和内存泄露共4页.pdf.zip

    解决Java内存溢出和内存泄露的方法主要包括以下几点: 1. 适当调整JVM参数:通过设置-Xms和-Xmx指定堆内存的初始大小和最大大小,避免因动态扩展导致的溢出。同时,可以通过-Xss设置线程栈的大小,防止栈溢出。 2....

    解决Java程序内存溢出的办法

    在Java编程中,内存溢出(Out of Memory Error,简称OOM)是一个常见的问题,它发生在程序请求的内存超过了系统能够分配的最大额度。这种情况通常会导致程序崩溃,因此理解如何解决Java程序的内存溢出至关重要。以下...

    java IBM websphere 内存溢出 javacore deapdump CPU内存分析工具

    在处理Java内存溢出问题时,除了使用上述工具外,还需要理解以下几个关键概念: 1. 堆内存:Java对象主要存储在堆内存中,过大或过多的对象可能导致堆溢出。 2. 非堆内存:包括JVM自身使用的内存(如方法区、元空间...

    maven内存溢出解决放啊

    本文将详细介绍如何在不同环境下解决Maven构建过程中出现的内存溢出问题。 #### 二、内存溢出原因分析 在深入探讨解决方案之前,我们需要先理解为何会出现内存溢出的情况。通常情况下,Maven构建过程中的内存溢出...

    was内存溢出 javacore分析工具jca 456

    总之,对于WebSphere内存溢出问题,Javacore分析工具JCA 456是开发者的重要助手,它能帮助我们快速定位问题,有效地解决问题,保证系统的稳定运行。正确理解和使用这类工具,对于提升企业应用的性能和可靠性至关重要...

    内存溢出问题修改

    通过对Java虚拟机内存区域的理解、合理的内存配置以及代码层面的优化,可以有效地解决内存溢出问题,提高应用的稳定性和响应速度。此外,使用适当的监控工具和技术手段对内存使用情况进行实时监测,能够帮助开发者更...

    was内存溢出 javacore分析工具jca 401

    标题中的“was内存溢出 javacore分析工具jca 401”指的是在WebSphere应用服务器(WAS)环境中,出现内存溢出问题时,使用名为JCA(Java Core Analysis)401的工具进行分析的情况。内存溢出是程序运行过程中,因分配...

    某应用内存溢出(暨jvm)分析分享

    标题 "某应用内存溢出(暨jvm)分析分享" 提到的是一个关于应用程序,特别是N银行消费信贷backend应用的内存溢出问题及其在Java虚拟机(JVM)层面上的分析。内存溢出是程序运行时由于分配的内存不足导致无法继续执行...

Global site tag (gtag.js) - Google Analytics