• JVM学习六:堆分析


    一、内存溢出(OOM)的原因

    在JVM中,有哪些内存区间?
    堆溢出
    复制代码
    public static void main(String args[]){
        ArrayList<byte[]> list=new ArrayList<byte[]>();
        for(int i=0;i<1024;i++){
            list.add(new byte[1024*1024]);
        }
    }
    复制代码

    永久区
    复制代码
    生成大量的类
    public static void main(String[] args) {
        for(int i=0;i<100000;i++){
            CglibBean bean = new CglibBean("geym.jvm.ch3.perm.bean"+i,new HashMap());
        }
    }
    复制代码

    Java栈溢出
     
    这里的栈溢出指,在创建线程的时候,需要为线程分配栈空间,这个栈空间是向操作系统请求的,如果操作系统无法给出足够的空间,就会抛出OOM
    复制代码
    public static class SleepThread implements Runnable{
        public void run(){
            try {
                Thread.sleep(10000000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    public static void main(String args[]){
        for(int i=0;i<1000;i++){
            new Thread(new SleepThread(),"Thread"+i).start();
            System.out.println("Thread"+i+" created");
        }
    }
    复制代码

    直接内存溢出
    ByteBuffer.allocateDirect()无法从操作系统获得足够的空间
    for(int i=0;i<1024;i++){
        ByteBuffer.allocateDirect(1024*1024);
        System.out.println(i);
          System.gc();
    }

    二、MAT使用基础

    浅堆(Shallow Heap)与深堆(Retained Heap)
    显示入引用(incoming)和出引用(outgoing)
    支配树

    nMemory Analyzer(MAT)
    n基于Eclipse的软件
    nhttp://www.eclipse.org/mat/
     

     

                                            

     

     

     

    浅堆
    一个对象结构所占用的内存大小
     
    –3个int类型以及一个引用类型合计占用内存3*4+4=16个字节。再加上对象头的8个字节,因此String对象占用的空间,即浅堆的大小是16+8=24字节
    –对象大小按照8字节对齐
    –浅堆大小和对象的内容无关,只和对象的结构有关
     深堆
    –一个对象被GC回收后,可以真实释放的内存大小
    –只能通过对象访问到的(直接或者间接)所有对象的浅堆之和 (支配树)

     

     

    可以看到,所有的Point实例浅堆和深堆的大小都是16字节。而dLine对象,浅堆为16字节,深堆也是16字节,这是因为dLine对象内的两个点f和g没有被设置为null,因此,即使dLine被回收,f和g也不会被释放。对象cLine内的引用对象d和e由于仅在cLine内还存在引用,因此只要cLine被释放,d和e必然也作为垃圾被回收,即d和e在cLine的保留集内,因此cLine的深堆为16*2+16=48字节。
    对于aLine和bLine对象,由于两者均持有对方的一个点,因此,当aLine被回收时,公共点a在bLine中依然有引用存在,故不会被回收,点a不在aLine对象的保留集中,因此aLine的深堆大小为16+16=32字节。对象bLine与aLine完全一致。

    三、使用Visual VM分析堆

    – java自带的多功能分析工具,可以用来分析堆Dump

    类的柱状图 ,显示对象数量,总大小等:

     

    从类试图切换到实例试图,显示所有的实例:

     

     

    使用OQL查询:

     

    返回引用了(0,0)这个点的所有对象

     

    四、Tomcat OOM分析案例

    Tomcat 在接收大量请求时发生OOM,获取堆Dump文件,进行分析。

    如果是session过多引起OOM

    –  OOM由于保存session过多引起,可以考虑增加堆大小

    –  如果应用允许,缩短session的过期时间,使得session可以及时过期,并回收

    原文:https://www.cnblogs.com/pony1223/p/9206715.html

  • 相关阅读:
    luogu P1641 [SCOI2010]生成字符串
    luogu P2662 牛场围栏
    luogu P3193 [HNOI2008]GT考试
    luogu P3293 [SCOI2016]美味
    luogu P2048 [NOI2010]超级钢琴
    Wannafly挑战赛21 E 未来城市规划
    luogu P2770 航空路线问题
    luogu P4082 [USACO17DEC]Push a Box
    运维交流平台
    elk之[logstash-input-file]插件使用详解
  • 原文地址:https://www.cnblogs.com/guanbin-529/p/12945112.html
Copyright © 2020-2023  润新知