当前位置:网站首页>ArrayList # sublist these four holes, you get caught accidentally
ArrayList # sublist these four holes, you get caught accidentally
2022-06-24 11:34:00 【Hollis Chuang】
Hollis In the limited time discount for your new book , An in-depth explanation Java Basic dry goods notes !
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());End
My new book 《 In depth understanding of Java The core technology 》 It's on the market , After listing, it has been ranked in Jingdong best seller list for several times , At present 6 In the discount , If you want to start, don't miss it ~ Long press the QR code to buy ~

Long press to scan code and enjoy 6 A discount
Previous recommendation
3000 Frame animation illustration MySQL Why binlog、redo log and undo log
It's a hot topic : a monthly salary 2~3W The Manon of , How to spend the day ?
In terms of implementation principle ,Nacos Why so strong
There is Tao without skill , It can be done with skill ; No way with skill , Stop at surgery
Welcome to pay attention Java Road official account

Good article , I was watching ️
边栏推荐
- Any and typevar make the automatic completion of IDE better
- 图片的可视化呈现有效增强大屏吸引力
- Insurance app aging service evaluation analysis 2022 issue 06
- 《opencv学习笔记》-- 离散傅里叶变换
- 【老卫搞机】090期:键盘?主机?全功能键盘主机!
- System design: key features of distributed systems
- 电商红包雨是如何实现的?拿去面试用(典型高并发)
- 【206】使用php语言去生成go语言的代码
- Cloud vendor secondary virtualization restrictions
- 程序员大部分时间不是写代码,而是。。。
猜你喜欢
[Architect (Part 41)] installation of server development and connection to redis database

Turn 2D photos into 3D models to see NVIDIA's new AI "magic"!

《opencv学习笔记》-- 感兴趣区域(ROI)、图像混合

图片的可视化呈现有效增强大屏吸引力

GLOG从入门到入门

Group counting_ Structure and workflow of CPU

Qt: 判断字符串是否为数字格式

@RequestBody注解

Programmers spend most of their time not writing code, but...

ArrayList#subList这四个坑,一不小心就中招
随机推荐
[digital ic/fpga] booth multiplier
Group counting_ Structure and workflow of CPU
[深度学习][pytorch][原创]crnn在高版本pytorch上训练loss为nan解决办法
[Flink source code practice (I)] add a rest API to Flink
New progress in the construction of meituan's Flink based real-time data warehouse platform
Multi gate mixture of experts and code implementation
How to develop hospital information system (his) with SMS notification and voice function
math_ Summation and derivation of proportional series & derivation of sum and difference of equal powers / difference between two nth power numbers/
Cook a delicious cli
《opencv学习笔记》-- 矩阵归一化 normalize()函数
Qt: judge whether the string is in numeric format
5W1H talk about open source - what is open source?
怎么申请打新债 开户是安全的吗
What is the bin file for? How to open the file correctly
Tencent geek challenge small - endless!
Audio knowledge (III) -- MFCCs code implementation
Step 3: access the API interface for inquiry of SF express doc No. [express 100api interface]
A fault record of misoperation dhclient script
Why choose b+ tree as storage engine index structure
Self cleaning Manual of mining Trojan horse

