关于获取子集合的问题

来源:3-5 嵌套迭代,小心外面的过早耗尽!

骑着猪找未来

2021-03-15

一哥:
听说你现在很累,那么我就来提问题了。
List如果没设置好初始容量,在不停的添加元素进去的时候,导致List进行扩容,数据量大的时候,由于扩容需要进行复制操作,可能会导致OOM,那么我想了解下,途图中获取这个子集合的操作,会由于不停的复制数组而导致OOM吗?我自己做了个小测试,把一个具有700万字符串的List每次按1000的容量不停的切分,程序正常执行下来了。
图片描述

写回答

3回答

张勤一

2021-03-15

猪哥对不起:

    这个问题提的很好,我来做一个比较详细的解释吧。首先,扩容会导致 OOM 吗?其实,不是这么回事。

    (1)不断的往 List 中添加元素,如果超过了 List 原本的空间,那么,是会出现拷贝、扩容的情况,但是,扩容之后,原来的空间(老的 List)在 GC 的时候就被直接回收掉了,因为没有任何引用指向它了;

    (2)那么,为什么还会出现 OOM 呢?其实与扩容的关系不大,而是因为你要填充的数据量太多,且这些数据都是不能被 GC 回收的。所以,当堆内存空间实在是分配不了的时候,就会 OOM 了。


    图中的这个操作会导致 OOM 吗?可以肯定的说,不会!

    (1)你的数据已经全部被塞入 teleNos 中了,此时还没有发生 OOM,那么,说明堆内存空间够用

    (2)你通过 for 循环去拆分 subList,你要知道,每经历一次 for 循环,上一个 subList 就直接被回收了,因为已经没有引用直接指向它了;

    (3)而在整体退出 for 循环之后,堆内存也只会有 teleNos,因为所有的 subList 都会被 GC 回收掉(超出作用域,没有引用了)

    那么,只剩下刚刚进来的第一个 subList 会和 teleNos 同时占据堆内存空间;不过,subList 是拷贝原数组还是只是指针指向呢?去看看源码,你就知道答案了。


    我是勤一,欢迎随时找我!

1
0

张勤一

2021-03-15

猪哥对不起:

    这个问题提的很好,我来做一个比较详细的解释吧。首先,扩容会导致 OOM 吗?其实,不是这么回事。

    (1)不断的往 List 中添加元素,如果超过了 List 原本的空间,那么,是会出现拷贝、扩容的情况,但是,扩容之后,原来的空间(老的 List)在 GC 的时候就被直接回收掉了,因为没有任何引用指向它了;

    (2)那么,为什么还会出现 OOM 呢?其实与扩容的关系不大,而是因为你要填充的数据量太多,且这些数据都是不能被 GC 回收的。所以,当堆内存空间实在是分配不了的时候,就会 OOM 了。


    图中的这个操作会导致 OOM 吗?可以肯定的说,不会!

    (1)你的数据已经全部被塞入 teleNos 中了,此时还没有发生 OOM,那么,说明堆内存空间够用

    (2)你通过 for 循环去拆分 subList,你要知道,每经历一次 for 循环,上一个 subList 就直接被回收了,因为已经没有引用直接指向它了;

    (3)而在整体退出 for 循环之后,堆内存也只会有 teleNos,因为所有的 subList 都会被 GC 回收掉(超出作用域,没有引用了)

    那么,只剩下刚刚进来的第一个 subList 会和 teleNos 同时占据堆内存空间;不过,subList 是拷贝原数组还是只是指针指向呢?去看看源码,你就知道答案了。


    我是勤一,欢迎随时找我!

1
0

张勤一

2021-03-15

猪哥对不起:

    这个问题提的很好,我来做一个比较详细的解释吧。首先,扩容会导致 OOM 吗?其实,不是这么回事。

    (1)不断的往 List 中添加元素,如果超过了 List 原本的空间,那么,是会出现拷贝、扩容的情况,但是,扩容之后,原来的空间(老的 List)在 GC 的时候就被直接回收掉了,因为没有任何引用指向它了;

    (2)那么,为什么还会出现 OOM 呢?其实与扩容的关系不大,而是因为你要填充的数据量太多,且这些数据都是不能被 GC 回收的。所以,当堆内存空间实在是分配不了的时候,就会 OOM 了。


    图中的这个操作会导致 OOM 吗?可以肯定的说,不会!

    (1)你的数据已经全部被塞入 teleNos 中了,此时还没有发生 OOM,那么,说明堆内存空间够用

    (2)你通过 for 循环去拆分 subList,你要知道,每经历一次 for 循环,上一个 subList 就直接被回收了,因为已经没有引用直接指向它了;

    (3)而在整体退出 for 循环之后,堆内存也只会有 teleNos,因为所有的 subList 都会被 GC 回收掉(超出作用域,没有引用了)

    那么,只剩下刚刚进来的第一个 subList 会和 teleNos 同时占据堆内存空间;不过,subList 是拷贝原数组还是只是指针指向呢?去看看源码,你就知道答案了。


    我是勤一,欢迎随时找我!

1
0

Java实操避坑指南 SpringBoot/MySQL/Redis错误详解

掌握业务开发中各种类型的坑,,Java web开发领域通用

466 学习 · 204 问题

查看课程