当前位置:网站首页>ArrayList # sublist these four holes, you get caught accidentally
ArrayList # sublist these four holes, you get caught accidentally
2022-06-26 03:01:00 【Java confidant_】
Today, let's have a steak ArrayList#subList Four pits of .
One 、 Memory leak caused by improper use
Let's first show you a simple but interesting code
public class OrderService {
public static void main(String[] args) {
OrderService orderService = new OrderService();
orderService.process();
}
public void process() {
List<Long> orderIdList = queryOrder();
List<List<Long>> allFailedList = new ArrayList<>();
for(int i = 0; i < Integer.MAX_VALUE; i++) {
System.out.println(i);
List<Long> failedList = doProcess(orderIdList);
allFailedList.add(failedList);
}
}
private List<Long> doProcess(List<Long> orderIdList) {
List<Long> failedList = new ArrayList<>();
for (Long orderId : orderIdList) {
if (orderId % 2 == 0) {
failedList.add(orderId) ;
}
}
// Take only one failed order id Do analysis
return failedList.subList(0, 1);
}
private List<Long> queryOrder() {
List<Long> orderIdList = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
orderIdList.add(RandomUtils.nextLong());
}
return orderIdList;
}
} If you run this code on a local machine , And turn on arthas Monitor memory conditions :
Memory used total max usage
heap 2742M 3643M 3643M 75.28%
ps_eden_space 11M 462M 468M 2.52%
ps_survivor_space 0K 460288K 460288K 0.00%
ps_old_gen 2730M 2731M 2731M 99.99%
nonheap 28M 28M -1 97.22%
code_cache 5M 5M 240M 2.19%
metaspace 20M 20M -1 97.19%
compressed_class_space 2M 2M 1024M 0.25%
direct 0K 0K - 0.00%
mapped 0K 0K - 0.00% Less than 3GB Old age pawn i Cycle to about 60 It exploded when it was around 10000 , The largest object in our current heap is allFailedList At most 60 m Long Type List, Roughly, there are only a few dozen MB, It will not explode the memory at all . Then we have reason to suspect that the above code has a memory leak .
go back to ArrayList#subList Implementation code :
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
private class SubList extends AbstractList<E> implements RandomAccess {
private final AbstractList<E> parent;
private final int parentOffset;
private final int offset;
int size;
SubList(AbstractList<E> parent,
int offset, int fromIndex, int toIndex) {
this.parent = parent;
this.parentOffset = fromIndex;
this.offset = offset + fromIndex;
this.size = toIndex - fromIndex;
this.modCount = ArrayList.this.modCount;
}
} You can see , Every time you call ArrayList#subList It will generate a SubList object , And this object's parent The attribute value holds the original ArrayList References to , This makes sense ,allFailedList Hold all previous calls queryOrder Produced List object , These objects are eventually transferred to the elderly generation without release .
Two 、 Improper use causes dead circulation
Let's look at another piece of code :
public class SubListDemo {
public static void main(String[] args) {
List<Long> arrayList = init();
List<Long> subList = arrayList.subList(0, 1);
for (int i = 0; i < arrayList.size(); i++) {
if (arrayList.get(i) % 2 == 0) {
subList.add(arrayList.get(i));
}
}
}
private static List<Long> init() {
List<Long> arrayList = new ArrayList<>();
arrayList.add(RandomUtils.nextLong());
arrayList.add(RandomUtils.nextLong());
arrayList.add(RandomUtils.nextLong());
arrayList.add(RandomUtils.nextLong());
arrayList.add(RandomUtils.nextLong());
return arrayList;
}
} If I say that the above code is an endless loop , Would you be surprised . go back to subList The implementation of the
// AbstractList
public boolean add(E e) {
add(size(), e);
return true;
} Then it will call ArrayList Methods
public void add(int index, E e) {
rangeCheckForAdd(index);
checkForComodification();
parent.add(parentOffset + index, e);
this.modCount = parent.modCount;
this.size++;
} You can see , call subList Of add In fact, it is in the original ArrayList Add elements , Therefore, the original arrayList.size() Will always get bigger , Eventually lead to a dead cycle .
3、 ... and 、 Be able to subList Heyuan List Make structural changes
public static void main(String[] args) {
List<String> listArr = new ArrayList<>();
listArr.add("Delhi");
listArr.add("Bangalore");
listArr.add("New York");
listArr.add("London");
List<String> listArrSub = listArr.subList(1, 3);
System.out.println("List-: " + listArr);
System.out.println("Sub List-: " + listArrSub);
//Performing Structural Change in list.
listArr.add("Mumbai");
System.out.println("\nAfter Structural Change...\n");
System.out.println("List-: " + listArr);
System.out.println("Sub List-: " + listArrSub);
} This code will eventually throw ConcurrentModificationException
List-: [Delhi, Bangalore, New York, London]
Sub List-: [Bangalore, New York]
After Structural Change...
List-: [Delhi, Bangalore, New York, London, Mumbai]
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1231)
at java.util.ArrayList$SubList.listIterator(ArrayList.java:1091)
at java.util.AbstractList.listIterator(AbstractList.java:299)
at java.util.ArrayList$SubList.iterator(ArrayList.java:1087)
at java.util.AbstractCollection.toString(AbstractCollection.java:454)
at java.lang.String.valueOf(String.java:2982)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at infosys.Research.main(Research.java:26) Look at the simple ArrayList Source code :
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private void ensureExplicitCapacity(int minCapacity) {
// Note that this line is correct for the original list Of modCount This variable is incremented
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
} it is to be noted that , Call the... Of the original array add Method has modified the original array modCount attribute , When the program is executed to print subList This line of code calls Sublist#toString Method , Finally, the following private method will be called :
private void checkForComodification() {
if (ArrayList.this.modCount != this.modCount)
throw new ConcurrentModificationException();
} According to the previous analysis , primary ArrayList Of modCount The attribute has been self incremented , therefore ArrayList.this.modCount != this.modCount The result of the execution is true, And then eventually it sold out ConcurrentModificationException abnormal .
About modCount This attribute ,Oracle There is also a detailed description in the document
The number of times this list has been structurally modified. Structural modifications are those that change the size of the list.
Which translates as :
modCount The record is List Number of structural modifications , The so-called structural modification refers to the ability to change List Size operation
If there is no knowledge reserve in advance , This kind of abnormality is difficult to check
Four 、 As RPC Serialization failed when the interface enters parameters
From above SubList You can see the definition of ,SubList It didn't happen Serializable Interface , So in some dependencies Java Native serialization protocol RPC Serialization fails in the framework of , Such as Dubbo etc. .
5、 ... and 、 Best practices
subList The original design List A view of , It is often used in read-only scenarios , This is different from what most people understand , Even if only used in read-only scenarios , It is also prone to memory leaks , Moreover, the existence of this view does not allow the original List and SubList Make structural changes , Personally think that subList This Api The design of the is terrible , Try to avoid using... Directly in your code ArrayList#subList, obtain List Of subList There are two best practices :
5.1 Copy to the new ArrayList in
ArrayList myArrayList = new ArrayList();
ArrayList part1 = new ArrayList(myArrayList.subList(0, 25));
ArrayList part2 = new ArrayList(myArrayList.subList(26, 51));5.2 Use lambda expression
dataList.stream().skip(5).limit(10).collect(Collectors.toList());
dataList.stream().skip(30).limit(10).collect(Collectors.toList());recommend
Technical involution group , Learn together !!

PS: Because the official account platform changed the push rules. , If you don't want to miss the content , Remember to click after reading “ Looking at ”, Add one “ Star standard ”, In this way, each new article push will appear in your subscription list for the first time . spot “ Looking at ” Support us !
边栏推荐
- UE5全局光照系统Lumen解析与优化
- Redis Lua sandbox bypass command execution (cve-2022-0543)
- How to default that an app is not restricted by traffic
- UTONMOS:以数字藏品助力华夏文化传承和数字科技发展
- Termux install openssh
- 记一个RestControll和Controller 引起的折磨BUG
- 【解决】联想拯救者vmware启动虚拟机蓝屏重启问题
- ArrayList#subList这四个坑,一不小心就中招
- Never criticize
- Which securities company should I choose to open an account online? Is it safe to open an account online?
猜你喜欢

【解决】联想拯救者vmware启动虚拟机蓝屏重启问题

UE5全局光照系统Lumen解析与优化

多测师拱墅肖sir_工作目录下的use websocket报错解决方案

OpenAPI 3.0 specification - Food Guide

【解决】CMake was unable to find a build program corresponding to “Unix Makefiles“.
![[machine learning] case study of college entrance examination prediction based on multiple time series](/img/13/7368a169d07e01d86a2d2c0207ccca.png)
[machine learning] case study of college entrance examination prediction based on multiple time series

学习太极创客 — MQTT(五)发布、订阅和取消订阅

Components and routing

Little p weekly Vol.10
![[machinetranslation] - Calculation of Bleu value](/img/c3/8f98db33eb0ab5a016621d21d971e4.png)
[machinetranslation] - Calculation of Bleu value
随机推荐
OpenAPI 3.0 specification - Food Guide
【QT】自定义控件-空气质量仪表盘
Camtasia 2022 new ultra clear recording computer video
Learn Tai Chi Maker - mqtt (IV) server connection operation
Create a nonlinear least squares test in R
How to delete gridlines in ggplot2 (with examples)
Share some remote office experience in Intranet operation | community essay solicitation
Utonmos: digital collections help the inheritance of Chinese culture and the development of digital technology
【机器学习】基于多元时间序列对高考预测分析案例
Limit the input character length to 1 character in English and 2 characters in Chinese
附加:HikariCP连接池简述;(并没有深究,只是对HikariCP连接池有个基本认识)
[机器翻译]—BLEU值的计算
[solution] cmake was unable to find a build program corresponding to "UNIX makefiles"
请指教同花顺软件究竟是什么?在线开户安全么?
The "more" option of Spreadtrum platform dearmcamera2 is removed
限制输入字符长度length英文1个字符中文2个字符
数据库查询语句SQL中like、%、-的区别
组件与路由
What can Arthas do for you?
OpenAPI 3.0 specification - Food Guide