当前位置:首页 > 科技  > 软件

终于明白为啥面试老是有人问 SubList 了,原来这玩意会 OOM!

来源: 责编: 时间:2024-03-18 09:33:25 101观看
导读最近刚做到一个内存分页的需求,自测了几次就 OOM 了,找了半天原因,终于把这个坑填上来,下面整理一下发出来,各位小伙伴引以为鉴。我们经常会使用 List.subList 方法对 List 进行切片,比如取前十个元素出来用,但是和 Arrays.a

最近刚做到一个内存分页的需求,自测了几次就 OOM 了,找了半天原因,终于把这个坑填上来,下面整理一下发出来,各位小伙伴引以为鉴。5XE28资讯网——每日最新资讯28at.com

我们经常会使用 List.subList 方法对 List 进行切片,比如取前十个元素出来用,但是和 Arrays.asList 的问题类似(具体文章可以看 慎用 ArrayList,全是坑!),List.subList 返回的子 List 不是一个全新地址的 ArrayList,这个子 List 会和原始 List 相互影响。5XE28资讯网——每日最新资讯28at.com

如果不注意,很可能会因此产生 OOM 问题。5XE28资讯网——每日最新资讯28at.com

话不多说,先复现问题。如下代码所示,定义一个名为 data 的静态 List 用来存放 List<Integer> 类型,循环 1000 次,每次都从一个具有 100 万个 Integer 的 List 中(即代码中的 rawList),使用 subList 方法获得一个只包含一个数字的子 List,并把这个子 List 加入 data 变量:5XE28资讯网——每日最新资讯28at.com

图片图片5XE28资讯网——每日最新资讯28at.com

看起来,这个 data 变量里面最终保存的只是 1000 个具有 1 个元素的 List 而已,并不会出现什么问题啊。5XE28资讯网——每日最新资讯28at.com

但是,代码在运行到一段时间后,可以看到在我的机器上是第 159 次循环后发生了 OOM:5XE28资讯网——每日最新资讯28at.com

图片图片5XE28资讯网——每日最新资讯28at.com

出现 OOM 的原因是,循环中的 1000 个具有 100 万个元素的 List 始终得不到回收,因为它始终被 subList 方法返回的 List 强引用。5XE28资讯网——每日最新资讯28at.com

subList 返回的子 List 为啥会强引用原始的 List?再来做个实验看下:5XE28资讯网——每日最新资讯28at.com

首先初始化一个包含数字 1 到 10 的 ArrayList,然后通过调用 subList 方法取出 2、3、4,随后删除这个 SubList 中的元素数字 3。可以看到原始 List 中数字 3 被删除了,说明删除子 List 中的元素影响到了原始 List:5XE28资讯网——每日最新资讯28at.com

图片图片5XE28资讯网——每日最新资讯28at.com

图片图片5XE28资讯网——每日最新资讯28at.com

继续看,我们为原始的 ArrayList 增加一个元素数字 0,然后遍历 SubList 输出所有元素。代码运行后报错 java.util.ConcurrentModificationException:5XE28资讯网——每日最新资讯28at.com

图片图片5XE28资讯网——每日最新资讯28at.com

图片图片5XE28资讯网——每日最新资讯28at.com

分析下 ArrayList 的源码,看看为什么会是这样:5XE28资讯网——每日最新资讯28at.com

图片图片5XE28资讯网——每日最新资讯28at.com

  1. ArrayList 维护了一个 int 类型的 modCount 的字段,表示 List 结构性修改的次数。所谓结构性修改,指的是影响 List 大小的修改,所以 add 操作必然会改变 modCount 的值。
  2. 分析 subList 方法可以看到,获得的 List 其实是创建了一个内部类 SubList,并不是普通的 ArrayList。
  3. 在初始化内部类 SubList 的时候传入了 this,这个 SubList 中的 parent 字段就是原始的 List,初始化的时候,并没有把原始 List 中的元素复制到独立的变量中保存,所以双方对元素的修改都会互相影响。而且 SubList 强引用了原始的 List,所以大量保存这样的 SubList 其实也保存了大量原始的 List,从而导致 OOM。
  4. 分析 listIterator 方法可知,遍历 SubList 的时候会先获得迭代器,比较原始 ArrayList modCount 的值和 SubList 当前 modCount 的值,如果不想等,就会抛出 ConcurrentModificationException 异常。所以上述实验代码,我们在获得了 SubList 为原始 List 新增了一个元素,修改了原始 List 的 modCount,所以判等失败抛出异常。

综上,既然 SubList 和原始 List 会相互影响,那么避免相互影响的修复方式有两种:5XE28资讯网——每日最新资讯28at.com

  1. 不直接使用 subList 方法返回的 SubList,而是重新使用 new ArrayList,在构造方法传入 SubList,来构建一个独立的 ArrayList:
List<Integer> subList = new ArrayList<>(list.subList(1, 4));
  1. 对于 Java 8 使用 Stream 的 skip 和 limit API 来跳过流中的元素,以及限制流中元素的个数,同样可以达到 SubList 切片的目的:
List<Integer> subList = list.stream().skip(1).limit(3).collect(Collectors.toList());

5XE28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-76481-0.html终于明白为啥面试老是有人问 SubList 了,原来这玩意会 OOM!

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 用 React/Vue 不如用 JQuery,你知道吗?

下一篇: SpringCloud微服务中如何实现多端认证?

标签:
  • 热门焦点
  • K60至尊版刚预热 一加Ace2 Pro正面硬刚

    K60至尊版刚预热 一加Ace2 Pro正面硬刚

    Redmi这边刚如火如荼的宣传了K60 Ultra的各种技术和硬件配置,作为竞品的一加也坐不住了。一加中国区总裁李杰发布了两条微博,表示在自家的一加Ace2上早就已经采用了和PixelWo
  • 中兴AX5400Pro+上手体验:再升级 双2.5G网口+USB 3.0这次全都有

    中兴AX5400Pro+上手体验:再升级 双2.5G网口+USB 3.0这次全都有

    2021年11月的时候,中兴先后发布了两款路由器产品,中兴AX5400和中兴AX5400 Pro,从产品命名上就不难看出这是隶属于同一系列的,但在外观设计上这两款产品可以说是完全没一点关系
  • 5月安卓手机好评榜:魅族20 Pro夺冠

    5月安卓手机好评榜:魅族20 Pro夺冠

    性能榜和性价比榜之后,我们来看最后的安卓手机好评榜,数据来源安兔兔评测,收集时间2023年5月1日至5月31日,仅限国内市场。第一名:魅族20 Pro好评率:97.50%不得不感慨魅族老品牌还
  • 线程通讯的三种方法!通俗易懂

    线程通讯的三种方法!通俗易懂

    线程通信是指多个线程之间通过某种机制进行协调和交互,例如,线程等待和通知机制就是线程通讯的主要手段之一。 在 Java 中,线程等待和通知的实现手段有以下几种方式:Object 类下
  • 虚拟键盘 API 的妙用

    虚拟键盘 API 的妙用

    你是否在遇到过这样的问题:移动设备上有一个固定元素,当激活虚拟键盘时,该元素被隐藏在了键盘下方?多年来,这一直是 Web 上的默认行为,在本文中,我们将探讨这个问题、为什么会发生
  • 消费结构调整丨巨头低价博弈,拼多多还卷得动吗?

    消费结构调整丨巨头低价博弈,拼多多还卷得动吗?

    来源:征探财经作者:陈香羽随着流量红利的退潮,电商的存量博弈越来越明显。曾经主攻中高端与品质的淘宝天猫、京东重拾&ldquo;低价&rdquo;口号。而过去与他们错位竞争的拼多多,靠
  • 冯提莫签约抖音公会 前“斗鱼一姐”消失在直播间

    冯提莫签约抖音公会 前“斗鱼一姐”消失在直播间

    来源:直播观察提起&ldquo;冯提莫&rdquo;这个名字,很多网友或许听过,但应该不记得她是哪位主播了。其实,作为曾经的&ldquo;斗鱼一姐&rdquo;,冯提莫在游戏直播的年代影响力不输于现
  • 小米MIX Fold 3配置细节曝光:搭载领先版骁龙8 Gen2+罕见5倍长焦

    小米MIX Fold 3配置细节曝光:搭载领先版骁龙8 Gen2+罕见5倍长焦

    这段时间以来,包括三星、一加、荣耀等等有不少品牌旗下的最新折叠屏旗舰都得到了不少爆料,而小米新一代折叠屏旗舰——小米MIX Fold 3此前也屡屡被传
  • 利用职权私自解除被封帐号 Meta开除20多名员工

    利用职权私自解除被封帐号 Meta开除20多名员工

    11月18日消息,据外媒援引知情人士表示,过去一年时间内,Facebook母公司Meta解雇或处罚了20多名员工以及合同工,指控这些人通过内部系统以不当方式重置用户帐号,其
Top