内存溢出分析

溢出区域

  内存溢出分为堆内存溢出和栈内存溢出
  如果虚拟机在扩展堆时无法申请到足够大的内存空间时,就会抛出outOfMemoryError
  如果线程请求的栈深度大于虚拟机所允许的最大深度,则抛出StackOverflflowError

栈溢出

public class TestOverFlow {
    public static void main(String[] args) {
        pop();
    }
    public static void pop(){
        pop();
    }
}

 

堆溢出

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        while (true) {
            list.add("Hello");
        }
        //pop();
    }

 

  为了更好检测和查看溢出原因在运行前先设置jvm参数
  -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Users/xianghan/Desktop/bak -Xmx2m -Xms2m
  生成的二进制文件格式为hprof,可以使用jprofifile打开分析具体导致异常的代码

线程数过多导致堆溢出

PS:此代码慎执行!!!! !!!在执行前一定小心保存当前工作内容,防止机器卡死
复制代码
    public static void main(String[] args) { 
        try {
            while (true){ 
                Thread thread=new Thread(new Runnable() { 
                    @Override 
                    public void run() { 
                        while (true){ 
                            
                        }
                    } 
                }); 
                System.out.println(thread.getName()); 
                thread.start(); 
            } 
        } catch (Exception e) {
            e.printStackTrace(); 
        } 
    }
复制代码

常量池溢出

    // -Xmx10m -Xms10m
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        int i = 0;
        while (true) {
            list.add(String.valueOf(i++).intern());
        }
    }
String.intern()是一个Native方法,它的作用是:如果字符串常池中已包含一个等于此String对象的字符串,则返回代表池中这个字符串的String对象,否则将此String对象包含的字符串添加到常池中,并且返回此string对象的引用。在JDK1.6及之前的版本中,由于常池分配在永久代内,我们可以通过-XX:PermSize=10M -XX:MaxPermSize=10M。MaxPermSize限制方法区大小从而间接限制其中常量池的容量。

本机直接内存溢出

如果不指定MaxDirectMemorySize那么直接内存与堆内存一样大    PS:运行此代码风险较大直接死机
复制代码
    public static int _1MB=1024*1024; //-Xmx20M -XX:MaxDirectMemorySize=10M 
    public static void main(String[] args) throws Exception{ 
        Field unsafeField= Unsafe.class.getDeclaredFields()[0]; 
        unsafeField.setAccessible(true);
        Unsafe unsafe =(Unsafe) unsafeField.get(null); 
        while (true){ 
            unsafe.allocateMemory(_1MB); 
        } 
    }
复制代码

 

posted @   -Lucas  阅读(110)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示