探讨的问题
一直比较疑惑如果一个很大的list在内存中存储的话,会占用多少内存空间呢?太大的话,这部分数据会直接进入堆内存,从而可能导致频繁的full gc。下面结合基本数据类型组成的对象,组成的list,通过生成的文件的大小来分析这个问题。
//首先构造一个大的list转换成byte[],然后写入到文件里面去。
public class SerializeDemo {
public static void main(String[] args) {
try {
outputSerialize();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void outputSerialize() throws IOException {
List<Employee> list = new ArrayList<Employee>();
for(int i = 0 ; i < 1024 ; i ++){
Employee e = new Employee();
list.add(e);
}
//为了方便分析,文件名后缀随着对象的属性添加而加一
String fileName = "employee1.txt";
FileOutputStream fileOut = new FileOutputStream("D:/"+fileName);
ObjectOutputStream out = new ObjectOutputStream(fileOut);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(list);
oos.close();
byte[] bytes = baos.toByteArray();
baos.close();
out.write(bytes);
out.close();
fileOut.close();
}
}
//从一个空对象依次添加属性,方便判断
public class Employee implements Serializable{
private int age;
private long empNo;
private String name;
private String name1 = "fadfadfadfadfadfadfasdfa";
private Integer age1;
private Integer age2 = 11;
private double empNo1 =1D;
}
分析过程
为了方便计算,我把一个list,添加1024个对象来进行观察;- 首先是一个没有任何属性的空对象。文件大小为 7K 则空对象大小大约为7B;
- 然后添加一个int 类型 文件大小为 11k 这说明int 类型虚拟机分配的大小是4B;
- 然后添加一个long类型 文件大小为 19k 这说明long类型虚拟机分配的大小是8B;
- 然后添加一个没有赋初始值的String类型,文件大小为20K,说明没有初始化的string虚拟机分配为1B;
- 然后添加一个有赋初始值的String类型,文件大小变为25K,说明赋初始值的String虚拟机分配为5k
- 然后添加一个没有赋初始值的包装类Integer,文件大小为26K,分配为1b
- 然后添加一个有初始值的包装类Integer,文件大小为31K,分配了5b
依次生成的文件大小
结论
一方面印证了基本数据类型在的文件中存储的大小,可以参考我的上一篇
而另一方面,对包装类的使用,没有赋值的包装类能很好的节约内存空间。总结来说,一个20个字段的对象,大约占用内存大小为7+20*5 = 107B。如果是1000条数据的话就就是约107KB,如果有1000的并发,也就是107M。这个还是有点威胁的,可能导致fullGc。