Java普通对象的内存开销(区别于数组),在64位下无指针压缩,不考虑内存对齐(最多7字节),对象头8字节+指向类型信息的指针8字节=16字节
如下声明对象,B对象就比A对象多占用24字节,怎么又多了8个字节?因为B.data中存放的只是指向堆内对象的引用又占用了8字节
class A {
float data;
}
class B {
Float data;//指向堆中对象的引用
}
一个Float类型对象在64位下,内存占用是24字节(Float对象头8字节+指向Float类型信息的指针8字节+float数据4字节+4字节的内存对齐)
在(科普篇之Java堆内缓存优化-StringCache的使用-优快云博客)中曾提到过召回i2i相似词表中不但有主播id,每个主播id还有一个Float类型的分数用于在线召回时进行排序截断
class AidScore1 {
String aid;
Float score;
}
class AidScore2 {
String aid;
float score;
}
由于基本类型本身占用内存比较小,AidScore2.score占用8个字节(4字节的float+4字节内存对齐),而使用一个包装类型做为类成员变量AidScore1.score就会占用24字节(指向堆中Float对象的引用8字节+Float对象头8字节+指向Float类型信息的指针8字节),使用一个包装类型Float就会多占用16字节,如果当堆内缓存中存在大量的包装类型时,就会额外占用大量内存
在我们的场景中使用float替换Float后通过对比垃圾回收后的内存占用,粗略估计减少了近2G的内存使用
优化前
优化后