• Java虚拟机内存溢出异常--《深入理解Java虚拟机》学习笔记及个人理解(三)


    Java虚拟机内存溢出异常--《深入理解Java虚拟机》学习笔记及个人理解(三)

    书上P39

    1. 堆内存溢出

    不断地创建对象, 而且保证创建的这些对象不会被回收即可(让GC Root可达).

    /**
     * 堆内存溢出demo
     * VM Options: -Xms6m -Xmx6m
     */
    public class HeapOOM {
        static class OOMObejct {
    
        }
    
        public static void main(String[] args) {
            List<OOMObejct> list = new ArrayList<>();
            while (true) {
                list.add(new OOMObejct());
            }
        }
    }
    

     会内存溢出, 输出结果如下:

    如果是用下面这段代码的话, 是不会内存溢出的. 因为有GC. 每次new 的 Object在下次for循环中都退出了作用域, 虚拟机栈不再持有对象的引用. 所以会被GC掉. 不会溢出.

    /**
     * 堆内存溢出demo
     * VM Options: -Xms6m -Xmx6m
     */
    public class HeapOOM {
        static class OOMObejct {
    
        }
    
        public static void main(String[] args) {
            while (true) {
                new OOMObejct();
            }
        }
    }
    

     visualVM的堆内存图如下:

    2. 虚拟机栈溢出

    /**
     * 栈内存溢出demo
     * VM Options: -Xms6m -Xmx6m
     */
    public class StackOverflow {
        private int stackDepth;
    
        private void stackLeak() {
            stackDepth++;
            stackLeak();
        }
    
        public static void main(String[] args) {
            StackOverflow oom = new StackOverflow();
            try {
                oom.stackLeak();
            } catch (Throwable e) {
                System.out.println(oom.stackDepth);
                System.err.println(e.toString());
            }
        }
    }

     输出结果如下(下面部分结果可能根据机器环境不同而不同):  

    3. 创建线程导致的内存溢出

    import java.util.concurrent.atomic.AtomicInteger;
    
    /**
     * 创建线程导致的内存溢出demo
     * VM Options: -Xms6m -Xmx6m
     */
    public class CreateThreadOOM {
        static AtomicInteger counter = new AtomicInteger(0);
    
        public static void main(String[] args) {
            while (true) {
                new Thread(() -> {
                    try {
                        System.out.println(counter.incrementAndGet());
                        Thread.sleep(Integer.MAX_VALUE);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }).start();
            }
        }
    }
    

     输出结果如下(下面部分结果可能根据机器环境不同而不同): 

    4. 直接内存溢出

    这段代码我这里没有运行出书上的效果...

    书上的意思应该是, 设定了直接内存大小最大为10M后, 继续申请的话, 就会报异常..

    在我电脑上, 虽然也设置了MaxDirectMemorySize=10m , 但是这玩意硬生生地申请了10G的虚拟内存也没停下, 最后被操作系统强制停止了.....(运行了几次电脑都快没电了)

    import sun.misc.Unsafe;
    
    import java.lang.reflect.Field;
    
    /**
     * VM Options: -Xms6m -Xmx6m -XX:MaxDirectMemorySize=10m
     */
    public class DirectMemoryOOM {
        private static final int _1MB = 1024 * 1014;
    
        public static void main(String[] args) throws IllegalAccessException, InterruptedException {
            Field unsafeFile = Unsafe.class.getDeclaredFields()[0];
            unsafeFile.setAccessible(true);
            Unsafe unsafe = (Unsafe) unsafeFile.get(null);
            while (true) {
                unsafe.allocateMemory(_1MB);
                Thread.sleep(10);
            }
        }
    }
    

      

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 拦截导弹
    Java实现 蓝桥杯VIP 算法训练 拦截导弹
    Java实现 蓝桥杯VIP 算法训练 回文数
    Java实现 蓝桥杯VIP 算法训练 回文数
    Java实现 蓝桥杯VIP 算法训练 集合运算
    好看的游戏soul calibur
    程序员的出路(要非常专一门技术才行,超过80%的同行,或者积累自己的类库和产品)
    Qt的版本历史
    红魔城传说:血色交响曲 (2009)(东方系列游戏,实在是太美了)
    QString和char字符数组之间的转换(QTextCodec.toUnicode方法,特别注意的问题)
  • 原文地址:https://www.cnblogs.com/noKing/p/9452710.html
Copyright © 2020-2023  润新知