这是一个已经被讨论了很久的问题了,能查到的答案各种都有,请问各位大佬们有什么高见?
小白我现在项目中遇到了类似的问题,循环遍历一个对象集合,然后取其中的某些属性放入另一个对象集合中,目前是在循环的过程中 new 了新的对象,然后放入新的 list 中。在联调的时还在循环的时候日志打印了新的实体对象,但是却内存溢出项目挂掉了。
很费解,list 的大小也就 2000 多个对象,有那么费内存吗?为什么会内存溢出?是不是将变量的声明放在循环外会好一些?希望大佬们能帮忙答疑,谢谢
1
Esioner 2019-12-30 15:35:51 +08:00
list 存的是对象的引用把,如果你把变量声明放到外面会导致数据异常的问题把
|
2
Arsenal16 2019-12-30 15:39:58 +08:00 via Android
list.stream().filter(你的过滤条件).map(你要映射的属性).collect(Collectors.toList());
Java8 的话直接用这个吧。 你那个又没代码,菜鸡如我,没法排查。 |
3
Arsenal16 2019-12-30 15:47:03 +08:00 via Android
你这个应该放在循环体内创建对象,然后添加到 list
|
4
cruii 2019-12-30 17:24:46 +08:00
这样问问题就跟不贴图说自己电脑蓝屏了怎么解决一样
|
5
matepi 2019-12-30 17:36:32 +08:00
不会,循环体内变量实际会被优化提前到循环起始前
和内存占用真正有关的是 new 动作 要看你其他代码,包括 new 动作里面进一步的 new |
6
zhaoritian19 OP @matepi 没有在 new 的实体对象里面进一步 new 别的对象,我也感觉单单是循环里面 new 实体对象不会导致内存溢出,而且才 1000 多个,GC 应该能处理的了。
|
7
zhaoritian19 OP @Arsenal16 老项目了用的 java7,没有升级到 java8。 如果是 8 就不会用循环来做了
|
8
chendy 2019-12-30 18:14:17 +08:00
内存溢出的话,用 -XX:+HeapDumpOnOutOfMemoryError 导出 dump,然后 mat 分析 dump 看是什么东西占用了太多内存
2000 不多,但是也不知道每个对象多大,所以不好说… |
9
passerbytiny 2019-12-30 18:16:27 +08:00
变量声明应该放到循环体外(然并卵,减少的内存占用相对来说可以忽略),但给 list 的对象一定是在循环体内 new 出来的。
list 上万都没问题,你这个能溢出应该是其他原因,需要根据 JVM 异常日志去定位。 |
10
palmers 2019-12-30 19:39:03 +08:00
得看看是堆内存还是栈内存 还有 同意 8#的同学把对应日志 dump 出来看看占用在哪里 问题原因应该就出来了
|
11
choice4 2019-12-31 01:04:00 +08:00 via Android
2000 个就溢出,,java 再费内存也没这么个费法啊
|
12
nnnToTnnn 2019-12-31 08:47:40 +08:00
Java 无论是在循环体内还是循环体外,由于 java 特定的 gc 机制,就算你在循环体内声明了变量,也不可能内存溢出!!!
除非有些引用没有被 gc,例如很简单的 ThreadLocal 中使用了 map,这种内存溢出的操作。 |
13
LaughingCat 2019-12-31 09:46:47 +08:00
我以前也遇到过这种循环 new 溢出的问题,当在循环次数达到一定数量时,new 操作会在占用大量的内存空间,解决方式是在外面 new 一个对象,这个对象有处理数据的构造函数,然后在循环里面对该对象进行构造函数赋值就能达到你要的循环 new 的效果。
|
14
rizon 2019-12-31 15:05:36 +08:00
这事我也很纠结,正常来说,从代码的可读性来说,放到循环体内生命更合适,但是很多人又说处于性能考虑应该放到循环体外。
我一般考虑可读性。 但是也是希望能得到一个更明确点的答案。 至于内存泄漏问题,在 java 里是不存在的,搞 C 的才有这个问题。 |
15
mightofcode 2020-01-06 11:55:22 +08:00
贴代码比较好,看描述看不明白
|