• 老李案例分享:定位JAVA内存溢出


    老李案例分享:定位JAVA内存溢出

     

       poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标。在poptest的loadrunner的培训中,为了提高学员性能优化的经验,加入了语言以及服务器方面的优化知识,为性能调优的能力打下基础。(大家对课程感兴趣,请加qq:564202718)

        

    项目中最佳实践:
    1. 编码规范认真执行。制定公司内部Java编码规范,让项目组成员遵守。
    2. 单元测试要覆盖所有分支与边界条件。 
    3. 代码审查。代码写完了,找资深程序猿走读代码。 
    4. 利用测试人员的能动性。 

    问题提示:
    java.lang.OutOfMemoryError: Java heap space 
    java.lang.OutOfMemoryError: PermGen space

    解决方法:
    a.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。

    b.java.lang.OutOfMemoryError: Java heap space:

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

    内存分配机制与gc是有联系,内存不够分配时gc释放不了堆内存。释放不了内存是因为内存还在用。java对象产生的堆内存占用,只要其不再被继续引用gc是能够顺利回收的
    问题的关键就找到了,当产生heap space内存溢出时,堆内存中对象数量过多的就可能是问题的根源了。例外的情况是,程序确实需要那么多内存,这时就要考虑增大堆内存。

    辅助工具:
    jdk自带两个可视化工具来定位问题: 
    jdk/jconsole.exe jdk/jvisualvm.exe

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

     

    b. 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这个类的对象出了问题。 
    以上是一个演示问题产生及定位过程,生产环境的问题千奇百怪需要具体问题具体分析。 
    当堆内存巨大时可能要调整jdklibvisualvmetcvisualvm.conf文件中的-xms -xmx大小来导入转储文件。 
    生产环境为linux的较多,可以借助jdk自带的jmap来转储堆内存文件来分析。  

  • 相关阅读:
    selenium开发-C#/java/Python
    Web循环监控Java调用 / Java调用.net wcf接口
    网站循环加载监控-C#
    串口通信分析
    windows环境jar包部署到linux服务器,一键操作
    windows环境jar包部署到linux服务器,一键操作(帮助说明)
    Git+TortoiseGit使用帮助
    安装Docker
    MySQL报错信息:Warning: (1366, "Incorrect string value: '\xD6\xD0\xB9\xFA\xB1\xEA...' for column 'VARIABLE_VALUE' at row 489")
    txt文档中文乱码
  • 原文地址:https://www.cnblogs.com/poptest/p/4897019.html
Copyright © 2020-2023  润新知