OOM实战:堆内存溢出 虚拟机栈和本地方法栈溢出 jvm栈容量太小 栈帧太大 栈太小,导致线程分配少,创建更多的线程将导致oom 方法区和运行时常量池溢出

2022-07-25,,,,

文章目录

  • 堆内存溢出
  • 虚拟机栈和本地方法栈溢出
    • jvm栈容量太小
    • 栈帧太大
    • 栈太小,导致线程分配少,创建更多的线程将导致oom
  • 方法区和运行时常量池溢出

堆内存溢出

eclipse memory analyzer分析dump

package ch2;

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

/**
 * VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
 *Xms:最小值
 *Xmx:最大值
 *-XX:+HeapDumpOnOutOfMemoryError:导出快照
 * @author zzm
 */
public class HeapOOM {

    static class OOMObject {
    }

    public static void main(String[] args) {
        List<OOMObject> list = new ArrayList<OOMObject>();

        while (true) {
            list.add(new OOMObject());
        }
    }
}


虚拟机栈和本地方法栈溢出

stackoverflow:请求大于最大栈深度。
OOM:支持动态扩展,却无法申请到内存。
hotspotjvm不支持动态扩展,所以无oom异常。

jvm栈容量太小

package ch2;

/**
 * VM Args:-Xss128k
 *
 * @author zzm
 */
public class JavaVMStackSOF_1 {

    private int stackLength = 1;

    public void stackLeak() {
        stackLength++;
        stackLeak();
    }

    public static void main(String[] args) {
        JavaVMStackSOF_1 oom = new JavaVMStackSOF_1();
        try {
            oom.stackLeak();
        } catch (Throwable e) {
            System.out.println("stack length:" + oom.stackLength);
            throw e;
        }
    }
}

栈帧太大

package ch2;

/**
 * VM: JDK 1.0.2, Sun Classic VM
 *
 * @author zzm
 */
public class JavaVMStackSOF_3 {
    private static int stackLength = 0;

    public static void test() {
        long unused1, unused2, unused3, unused4, unused5,
                unused6, unused7, unused8, unused9, unused10,
                unused11, unused12, unused13, unused14, unused15,
                unused16, unused17, unused18, unused19, unused20,
                unused21, unused22, unused23, unused24, unused25,
                unused26, unused27, unused28, unused29, unused30,
                unused31, unused32, unused33, unused34, unused35,
                unused36, unused37, unused38, unused39, unused40,
                unused41, unused42, unused43, unused44, unused45,
                unused46, unused47, unused48, unused49, unused50,
                unused51, unused52, unused53, unused54, unused55,
                unused56, unused57, unused58, unused59, unused60,
                unused61, unused62, unused63, unused64, unused65,
                unused66, unused67, unused68, unused69, unused70,
                unused71, unused72, unused73, unused74, unused75,
                unused76, unused77, unused78, unused79, unused80,
                unused81, unused82, unused83, unused84, unused85,
                unused86, unused87, unused88, unused89, unused90,
                unused91, unused92, unused93, unused94, unused95,
                unused96, unused97, unused98, unused99, unused100;

        stackLength ++;
        test();

        unused1 = unused2 = unused3 = unused4 = unused5 =
                unused6 = unused7 = unused8 = unused9 = unused10 =
                        unused11 = unused12 = unused13 = unused14 = unused15 =
                                unused16 = unused17 = unused18 = unused19 = unused20 =
                                        unused21 = unused22 = unused23 = unused24 = unused25 =
                                                unused26 = unused27 = unused28 = unused29 = unused30 =
                                                        unused31 = unused32 = unused33 = unused34 = unused35 =
                                                                unused36 = unused37 = unused38 = unused39 = unused40 =
                                                                        unused41 = unused42 = unused43 = unused44 = unused45 =
                                                                                unused46 = unused47 = unused48 = unused49 = unused50 =
                                                                                        unused51 = unused52 = unused53 = unused54 = unused55 =
                                                                                                unused56 = unused57 = unused58 = unused59 = unused60 =
                                                                                                        unused61 = unused62 = unused63 = unused64 = unused65 =
                                                                                                                unused66 = unused67 = unused68 = unused69 = unused70 =
                                                                                                                        unused71 = unused72 = unused73 = unused74 = unused75 =
                                                                                                                                unused76 = unused77 = unused78 = unused79 = unused80 =
                                                                                                                                        unused81 = unused82 = unused83 = unused84 = unused85 =
                                                                                                                                                unused86 = unused87 = unused88 = unused89 = unused90 =
                                                                                                                                                        unused91 = unused92 = unused93 = unused94 = unused95 =
                                                                                                                                                                unused96 = unused97 = unused98 = unused99 = unused100 = 0;
    }

    public static void main(String[] args) {
        try {
            test();
        }catch (Error e){
            System.out.println("stack length:" + stackLength);
            throw e;
        }
    }
}

栈太小,导致线程分配少,创建更多的线程将导致oom

package ch2;

/**
 * VM Args:-Xss2M (这时候不妨设大些,请在32位系统下运行)
 *
 * @author zzm
 */
public class JavaVMStackOOM {

    private void dontStop() {
        while (true) {
        }
    }

    public void stackLeakByThread() {
        while (true) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    dontStop();
                }
            });
            thread.start();
        }
    }

    public static void main(String[] args) throws Throwable {
        JavaVMStackOOM oom = new JavaVMStackOOM();
        oom.stackLeakByThread();
    }
}

方法区和运行时常量池溢出

jdk7以后,由于运行时常量池在堆中,StringBuilder和intern返回是同一个引用

package ch2;

public class RuntimeConstantPoolOOM_2 {

    public static void main(String[] args) {
        //jdk7以后,由于运行时常量池在堆中,StringBuilder和intern返回是同一个引用
        String str1 = new StringBuilder("计算机").append("软件").toString();
        System.out.println(str1.intern() == str1);//true

        String str2 = new StringBuilder("ja").append("va").toString();//java本来就在池中了
        System.out.println(str2.intern() == str2);//false
    }
}

本文地址:https://blog.csdn.net/qq_35459198/article/details/111932970

《OOM实战:堆内存溢出 虚拟机栈和本地方法栈溢出 jvm栈容量太小 栈帧太大 栈太小,导致线程分配少,创建更多的线程将导致oom 方法区和运行时常量池溢出.doc》

下载本文的Word格式文档,以方便收藏与打印。