死循环while/for中new对象? 不怕 OOM 吗?

目录
  1. 1. 一、前言
  2. 2. 二、模拟在死循环中new对象
  3. 3. 三、结论

一、前言

今天遇到一个又去的问题,在死循环中new对象,会造成 OOM 吗?

把这问题发到技术群中,有说会,有说不会的,引起一片热论。

我们还是来个demo模拟一下,看看什么结果吧

二、模拟在死循环中new对象

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void main(String[] args) { 
while (true) {
try {
log.info("new");
//模拟new对象,加入10000条数据
Map<String,Integer> map =new HashMap<>();
for (int i = 0; i< 10000; i++){
map.put(""+i,i);
}
} catch (Exception e) {
log.error("exception!", e);
} finally {
try {
//等待2秒
TimeUnit.SECONDS.sleep(2);
} catch (Exception e) {
log.error("sleep exception!", e);
}
}
}
}

然后配合JDK的 Java VisuaLVM 工具检查堆空间的内存,找到 jdk的bin目录下 jvisualvm.exe 文件,双击打开即可。

打开之后,界面如下:

然后运行我们的demo之后这边的列表就会出现个代码执行的package,双击 ==> 监控 ==> 即可查看我们代码执行后JVM中堆空间的内存变化。

三、结论

等执行一段时间之后,根据上图可以发现堆空间中的内存到了一定值之后就会被GC回收,由此得到结论:

死循环中new对象,不会OOM,原因是每一轮循环之后对象就失去了引用,等到GC执行,对象就会被回收;

但是,如果我们的对象内存很大(例如:刚才的Map中put很多很多值进去),已经超过JVM的堆空间,就会OOM。

或者在while外部的list中不断添加元素,也会OOM。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class Test {
public static void main(String[] args) {
List<User> list = new ArrayList<User>();
while(true){
User u = new User();
u.setAge(1);
u.setName("zl");
list.add(u);
System.out.println(list.size());
}
}

static class User{
private long age;
private String name;
public long getAge() {
return age;
}
public void setAge(long age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}