Java如何模拟内存泄漏呢?
下文笔者讲述java中模拟内存泄漏说明,如下所示
内存泄漏简介
内存泄露(Memory Leak)简介: 程序在申请内存后 无法释放已申请的内存空间 一次内存泄露危害可以忽略 但程序长时间运行,每次泄漏一点点 常年累计后,将会使程序吃掉大量的内存,也没有释放 迟早有一天,会将所有的内存吃光 我们将这种现象称之为"内存泄漏"
内存泄漏的原因
1、静态集合类引起内存泄漏 像HashMap、Vector等的使用最容易出现内存泄露 这些静态变量的生命周期和应用程序一致 他们所引用的所有的对象Object也不能被释放 2、监听器 在java代码编写中 都需要和监听器打交道 通常一个应用当中会用到很多监听器 我们会调用一个控件的如 addXXXlistener() 等方法来增加监听器 释放对象时,忘记清理监听器,会导致内存泄漏 3、各种连接 如: 数据库连接(dataSourse.getConnection()) 网络连接(socket)和io连接 除非其显式调用其close()方法将其连接关闭 否则是不会自动被GC 回收的。 4、内部类和外部模块的引用 内部类的引用是比较容易遗忘的一种 而一旦没释放可能导致一系列的后继类对象没有释放 5、单例模式 不正确使用单例模式是引起内存泄漏 单例对象在初始化后将在JVM的整个生命周期中存在(以静态变量的方式) 当单例对象持有外部的引用 那么这个对象将不能被JVM正常回收 由于单例的静态特性使得其生命周期跟应用的生命周期一样长 如果使用不恰当的话,很容易造成内存泄漏例:编写一个内存泄漏的示例
/** * <p> * 模拟场景1: 静态集合属性内存泄露导致OOM * JVM启动参数 -Xms300M -Xmx300M -Xmn200M * (设置为300M可以查看内存泄漏,但恰好又不会发生内存溢出) * </p> */ @RestController @RequestMapping("/memory") public class MemoryLeakController { //静态集合 public static List<Double> list = new ArrayList<>(); @GetMapping("/leak") public void testMemoryLeak () throws InterruptedException { Thread.sleep(10000); System.out.println("Debug Point 1"); this.populateList(); System.out.println("Debug Point 3"); Thread.sleep(10000); System.gc(); //显示触发Full GC //(若是静态属性,则不起作用; 若是非静态属性,则内存马上回收) Thread.sleep(Integer.MAX_VALUE); // 让进程一直存在,不结束。 } // 往list属性中循环添加指定的随机数 public void populateList() { for (int i = 0; i < 10000000; i++) { // Double 占用内存字节240000000 // (大约240000000/1024/1024 = 228M) list.add(Math.random()); } System.out.println("Debug Point 2"); } }
nohup java -jar -Xms20M -Xmx20M -Xmn10M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./heapdump.hprof & //输入以上命令运行项目 nohup java -jar xxx.jar & 可以让jar包一直后台运行 java -jar -Xms300M -Xmx300M -Xmn100M test-0.0.1-SNAPSHOT.jar 设置jvm参数并运行项目
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。