一、Sublist导致OOM

代码

@Slf4jpublic classSubListDemo {public static voidsubListOOM() {

List> data = new ArrayList<>();for (int i = 0; i < 1000; i++) {

List rawList = IntStream.rangeClosed(1, 100000).boxed().collect(Collectors.toList());//构建一个100000个元素的list

data.add(rawList.subList(0, 1));

}

log.info("data.size(): " +data.size());

}

}

OOM

Exception in thread "File Watcher"java.lang.OutOfMemoryError: GC overhead limit exceeded

at java.io.File.listFiles(File.java:1212)

at org.springframework.boot.devtools.filewatch.FolderSnapshot.collectFiles(FolderSnapshot.java:63)

at org.springframework.boot.devtools.filewatch.FolderSnapshot.collectFiles(FolderSnapshot.java:67)

at org.springframework.boot.devtools.filewatch.FolderSnapshot.collectFiles(FolderSnapshot.java:67)

at org.springframework.boot.devtools.filewatch.FolderSnapshot.collectFiles(FolderSnapshot.java:67)

at org.springframework.boot.devtools.filewatch.FolderSnapshot.(FolderSnapshot.java:58)

at org.springframework.boot.devtools.filewatch.FileSystemWatcher$Watcher.getCurrentSnapshots(FileSystemWatcher.java:277)

at org.springframework.boot.devtools.filewatch.FileSystemWatcher$Watcher.scan(FileSystemWatcher.java:251)

at org.springframework.boot.devtools.filewatch.FileSystemWatcher$Watcher.run(FileSystemWatcher.java:236)

at java.lang.Thread.run(Thread.java:748)

Exception in thread"restartedMain"java.lang.reflect.InvocationTargetException

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:498)

at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)

Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded

at java.lang.Integer.valueOf(Integer.java:832)

at java.util.stream.IntPipeline$$Lambda$492/1604894031.apply(Unknown Source)

at java.util.stream.IntPipeline$4$1.accept(IntPipeline.java:250)

at java.util.stream.Streams$RangeIntSpliterator.forEachRemaining(Streams.java:110)

at java.util.Spliterator$OfInt.forEachRemaining(Spliterator.java:693)

at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)

at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)

at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)

at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)

at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)

at com.example.newdemo.SubListDemo.subListOOM(SubListDemo.java:17)

at com.example.newdemo.NewdemoApplication.main(NewdemoApplication.java:13)

分析

出现 OOM 的原因是,循环中的 1000 个具有 10 万个元素的 List 始终得不到回收,因为它始终被 subList 方法返回的 List 强引用。

public List subList(int fromIndex, inttoIndex) {

subListRangeCheck(fromIndex, toIndex, size);return new SubList(this, 0, fromIndex, toIndex);

}

parent 字段就是原始的 List。SubList没有copy一份自己的数据,而是完整的保留了原始的list。 SubList 是原始 List 的视图,并不是独立的 List, SubList 强引用了原始的 List,所以大量保存这样的 SubList 会导致 OOM。

解决

不直接使用 subList 方法返回的 SubList,而是重新使用 new ArrayList,在构造方法传入 SubList,来构建一个独立的 ArrayList。sublist直接释放-》原始的list也被释放。

public static voidsubListWithoutOOM() {

List> data = new ArrayList<>();for (int i = 0; i < 1000; i++) {

List rawList = IntStream.rangeClosed(1, 100000).boxed().collect(Collectors.toList());//构建一个100000个元素的list

data.add(new ArrayList<>(rawList.subList(0, 1)));

}

log.info("data.size(): " +data.size());

}

另外一个例子

public static voidremoveSubList() {

List rawList = IntStream.rangeClosed(1, 10).boxed().collect(Collectors.toList());

List subList = rawList.subList(0, 3);

subList.remove(0);

rawList.forEach(System.out::print);

}

2345678910

可以看到,移除sublist的元素后,直接影响到了原始list。

二、修改原始列表后SubList循环报错

测试代码

public static voidaddItemToOriginalList() {

List rawList = IntStream.rangeClosed(1, 10).boxed().collect(Collectors.toList());

List subList = rawList.subList(0, 3);

rawList.add(11);try{

subList.forEach(System.out::print);

}catch(Exception ex)

{

ex.printStackTrace();

}

}

java.util.ConcurrentModificationException

at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1239)

at java.util.ArrayList$SubList.listIterator(ArrayList.java:1099)

at java.util.AbstractList.listIterator(AbstractList.java:299)

at java.util.ArrayList$SubList.iterator(ArrayList.java:1095)

at java.lang.Iterable.forEach(Iterable.java:74)

at com.example.newdemo.SubListDemo.addItemToOriginalList(SubListDemo.java:46)

at com.example.newdemo.NewdemoApplication.main(NewdemoApplication.java:13)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:498)

at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)

分析

modCount 的字段,表示结构性修改的次数--影响list size修改测次数,add肯定影响size,导致modCount加1.但是sublist的modCount没有变,所有抛出了异常。

代码

private voidcheckForComodification() {if (ArrayList.this.modCount != this.modCount)throw newConcurrentModificationException();

}

java list sublist_Java List的SubList使用问题相关推荐

  1. java sublist_java 中List.subList 总结

    今天,维护以前的代码,看到了List.subList这个方法,以前没接触过,对这个就是个小白,今天学习下: java.util.List中有一个subList方法,用来返回一个list的一部分的视图. ...

  2. java sublist_java中的subList

    package test; import java.util.ArrayList; import java.util.List; //对parentList进行结构性修改,访问subList会抛出异常 ...

  3. java sublist_java中List.subList()方法的使用

    sublist返回的东西,官方解释:Returns a view of the portion of this list between the specified fromIndex, inclus ...

  4. java中list中sublist_Java 中 List.subList() 方法的使用陷阱

    前言 本文原先发表在我的 iteye博客: http://clevergump.iteye.com/admin/blogs/2211979, 但由于在 iteye发表的这篇文章的某些渲染曾经出现过一些 ...

  5. Java中List集合的subList方法

    目录 一.说明 二.测试 1.直接输出 2.向subList中添加元素再输出 3. 从subList中删除元素再输出 4.向list中添加元素再输出 5.从list中删除一个元素后再输出 ​ 6.向l ...

  6. java中list中的subList方法

    List<Object> list = new Arraylist<>(); List<Object> subList = list.subList(0, 5); ...

  7. java sublist_Java subList的使用

    1. 在看<阿里巴巴java编程手册的时候>有如下强制约束 顺便学了一下subList. java.util.List中有一个subList方法,用来返回一个list的一部分的视图. Li ...

  8. java sublist_java 中sublist的使用

    http://blog.csdn.net/sbfivwsll/article/details/6557611 java List.subList方法中的超级大陷阱 在使用集合中,可能常常需要取集合中的 ...

  9. Java中的subList方法

    Java中的subList方法 今天看到了java中List中有个subList的方法,感觉很熟悉有没有?没错,在Stirng类中,也有个类似的方法:subString. Stirng中的subStr ...

最新文章

  1. [置顶] 归并排序,逆序数
  2. Java使用JAX-WS来写webservice时 Unable to create JAXBContext
  3. 【深入浅出项目管理视频1】-项目文档评审
  4. 17.Spark第1部分
  5. MFC的程序,不想显示窗口,任务栏里也不显示
  6. LeetCode 1110. 删点成林(二叉树递归)
  7. centos/Linux 解决使用sudo命令时xxx is not in the sudoers file.This incident will be reported
  8. [转载] 利用python制作简单计算器
  9. 7.1 封装(Java包(package)的概念+访问权限修饰符(public/private/protected/default))
  10. natapp软件使用
  11. BT5R3安装及汉化
  12. 鸿蒙系统服务器在哪,鸿蒙的服务中心怎么打开?鸿蒙服务中心打开及关闭教程...
  13. 外贸企业出口退税流程/经验分享
  14. 如何理解刑法中的“以非法占有为目的”
  15. L1-061 新胖子公式 (10 分)
  16. 浅谈简单快捷的服务器——私有云服务器!
  17. 轻松易懂的CSS学习权威指南来了
  18. 涂鸦小程序——为自己的人生画上一笔
  19. [ERP/鼎捷E10]VMI业务在E10中的处理
  20. java课程设计之球球大作战

热门文章

  1. 从编程角度来看此次乐言利用bug上分事件
  2. 关于8位指针强制转16位隐晦问题
  3. 文字根据图片环绕 + 显示文字两行后省略号
  4. 【渝粤教育】国家开放大学2018年春季 8612-21T传染病护理学 参考试题
  5. 记录服务器宕机事件:解决dell服务器system halted的方法
  6. 计算机术语表达祝福,祝福新人的唯美句子
  7. 计算机办公文员是干什么的,文员的基本电脑知识是什么? 文员的基本要求有哪些?...
  8. (others)U-Boot启动代码分析
  9. 绝地求生服务器维护5.27,绝地求生5月27日维护到几点进游戏 今天吃鸡更新维护公告...
  10. win10窗口分屏快捷键