那么我们如何来构建一个堆内存溢出呢?其实很简单,我们只要定义一个List
对象,然后通过一个循环不停的往List
里面塞对象。因为只要Controller不被回收,那么它里面的成员变量也是不会被回收的。这样就会导致List里面的对象越来越多,占用的内存越来越大,最后就把我们的内存撑爆了。
创建User对象
这里我们先创建一个User对象。
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
}
创建Controller对象
接下来我们来创建一个Controller来不停的往List集合中塞对象。
@RestController
public class MemoryController {
private List<User> userList = new ArrayList<User>();
/**
* -Xmx32M -Xms32M
* */
@GetMapping("/heap")
public String heap() {
int i=0;
while(true) {
userList.add(new User(i++, UUID.randomUUID().toString()));
}
}
}
配置项目启动时jvm的内存的大小
为了更快达到我们的效果,我们给springBoot项目启动时配置jvm的内存的大小。
-Xms30m -Xmx32m
理论知识:
1、默认堆空间大小是根据物理机内存大小决定的。
假设物理机是 16G 内存,那么 虚拟机的默认堆空间大小 如下:
最小值:16 / 64 = 0.25G * 1024 = 256 m
最大值:16 / 4 = 4G
2、以上只是“理论值”,“实际值”会比“理论值”小一些。
堆空间大小设置(多图):
如图:【Services】>【****SpringbootApplication】>【鼠标右键】>【Edit Configuration... Or 快捷键Shift+F4】
鼠标单击【Environment】Or 快捷键Alt+M
【VM options:】>
-Xms30m -Xmx32m
有人建议两个值相等,我倒是觉得没什么,这个看你个人喜好吧
验证生效与否:
System.out.println("-------------======= 华丽的分割线 =========----------");
//返回Java虚拟机中的堆内存总量
long xmsMemory = Runtime.getRuntime().totalMemory() / 1024 / 1024;
//返回Java虚拟机中使用的最大堆内存
long xmxMemory = Runtime.getRuntime().maxMemory() / 1024 / 1024;
System.out.println("-Xms:" + xmsMemory + "M");
System.out.println("-Xmx:" + xmxMemory + "M");
// System.out.println("系统内存大小为:" + xmsMemory * 64.0 / 1024 + "G");
// System.out.println("系统内存大小为:" + xmxMemory * 4.0 / 1024 + "G");
// 在使用 -Xms500m -Xmx500m -XX:+PrintGCDetails需要把等待时间代码注释掉
// try {
// Thread.sleep(1000000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
代码贴哪里看你喜好,我这里直接贴在启动类了
启动项目看效果
访问接口,出现内存溢出报错
Exception in thread "http-nio-8081-Poller" java.lang.OutOfMemoryError: GC overhead limit exceeded