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参数并运行项目
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。


