有一个程序,有一段逻辑中,会多次调用一个函数,其返回一个List,List中最多有1万个对象,该函数大概调用9次,但是多次调用后却占用了几个G的内存。
List中存的对象TopResult是List中保存的对象,每个对象的大小是32字节,chefs和equipid指向的数组是复用的,占用内存不做考虑,recepeids指向的数组为new int[9],占用56字节,也就是一个TopResult对象占用88字节,1w个对象,也不过才859.375KB。
而整个函数中只有一个LinkedList,一个common-pool对象池(用来管理TopResult对象),然后剩下的都是一些int[],首先打印整个运行过程中 TopResult的创建次数, 9w多次,也不过几十M的大小而。
首先通过jvisualvm查看内存使用情况,发现有大量的Objec[]对象,这几个G的内存也都是被这些Objec[]占用了。
当时也怀疑是不是使用common-pool造成的,取消使用对象池后,内存情况并没有得到改善。
最后发现是因为是对LinikList调用了sort的锅。
Collections.sort(List<T> list, Comparator<?super T> c),而我传递的 list是一个LinkedList,然后LinkedList的sort方法继承自List接口中的sort方法,
List接口中的sort方法 LinkedList的toArray()第一行this.toArray(),这个方法会创建一个Object[]数组。因为sort被调用次数太多,导致Object[]占用了几个G的内存。
我特意统计了下, sort方法被调用了 78684次,每一次调用创建一个Object[10000], 也就是 (4*10000+12)*78684=31474544208字节,2.9G的大小。 最后将LinikList改成ArrayList解决问题。
sort方法调用次数至于为啥一开始使用LinkedList,因为有时候调用函数后,返回的List会为空,就想着LinkedList占用内存会少一点。
网友评论