计算java简单对象内存
计算java简单对象内存
1.前言
JavaClass基本结构:
| 名称 | 占用字节 |
|---|---|
| Class头 | 8字节 |
| oop指针 | 4字节 |
| 数据区域 | 不定 |
| padding | 补充到整个大小为8字节的倍数 |
1. Class头8个字节, 存储了比如这个实例目前的锁信息、目前属于的堆类型等;
2. oop指针,存储的是这个类的定义,比如Java反射可以拿到字段名称,方法名称这些值都是存储在这个指针所指向的定义中;
3. 数据区域,存放数据的区域,这里的结构区分主要是两种:数组和非数组。如果是数组,数据区域中还会包含这个数组的大小;
4. 64位JDK,开启指针压缩,对象头大小12byte,不开启指针压缩,对象头大小16byte;
5. Java8后,默认开启指针压缩。
2.基本认知
八大基础数据类型:
八大封装类型 (64位开启指针压缩):
指针类型:
32位、64位开启指针压缩:4字节
64位不开启指针压缩:8字节
对象类型:
16字节起步
枚举类型:
64位:8字节,类似基础数据类型,直接占地址空间,不会出现指针引用
3.简单计算Dog
对于如下Dog 的对象,实际计算其内存大小:
对象头12 byte + 子类字段数5 * 指针大小 4byte + 父类字段数5 * 指针大小 4byte + padding 4 byte = 56 byte,
那么生成3W对象后,内存占用: 30000 * 56 / 1000 = 1680 KByte,
Jprofile 托管结果:

4.简单计算Master
对于如下master的对象,实际计算其内存大小:
对象头12 byte + 子类字段数4 * 指针大小 4byte + padding 4 byte = 32 byte,
那么生成3W对象后,内存占用: 30000 * 32 / 1000 = 960 KByte,
Jprofile 托管结果:

5.那些不可忽略的数据

这里有3W+的Long,和3W+的Integer,其实是因为模型定义中故意定义的两个 字段:"入店编号"、"主人联系电话",
简单算算:
Integer : 对象头12 + int大小 4 = 16 byte, 累乘后 16 * 30000 / 1000 = 480 K;
Long: 对象头12 + long大小 8 + padding 4 = 24 byte, 累乘后 24* 30000 / 1000 = 720 K;
String: 对象头12 + hash大小 4 + char[]引用 4 + padding 4 = 24 byte,累乘后 24* 316936/ 1000 = 7606 K;-------------细心统计一下,三个模型里定义的字串属性,刚好10个,所以是基数3W的十倍
char[]: 对象头12 + 数组长度 4 + char大小 2 * N; N等于字串里字节的个数;
Map$Node: 对象头12 + hash大小 4 + key引用 4 + value 引用 4 + next引用 4 + padding 4 = 32 byte, 累乘后 32 * 32705 / 1000 = 1046 K;
所以尽量不要用基本数据类型的封装类型 !
因为如果是基本数据类型,long 只有8 byte,inte 4 byte,上面的测试,可以节省内存: (16 - 4 + 24 - 8) * 30000 / 1000 = 840K。当然似乎还是比不起String字段的少用。
6.示例代码
@Getter
@Setter
@ToString
@JsonNaming(PropertyNamingStrategy.KebabCaseStrategy.class)
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiModel("Dog")
public class Dog extends Pet {
@JsonProperty("color")
@ApiModelProperty(name = "color", value = "色泽描述")
private String color;
@JsonProperty("vaccinationTime")
@ApiModelProperty(name = "vaccinationTime", value = "最近注射疫苗时间")
private String vaccinationTime;
@JsonProperty("foodRations")
@ApiModelProperty(name = "foodRations", value = "宠物口粮偏好")
private String foodRations;
@JsonProperty("playTime")
@ApiModelProperty(name = "playTime", value = "带耍时间")
private String playTime;
@JsonProperty("describing")
@ApiModelProperty(name = "describing", value = "附加描述")
private String describing;
public Dog(String name, Integer serialNumber, String age, String breed, Master master) {
super(name, serialNumber, age, breed, master);
}
public void init(String color, String vaccinationTime,
String foodRations, String playTime, String describing) {
this.color = color;
this.vaccinationTime = vaccinationTime;
this.foodRations = foodRations;
this.playTime = playTime;
this.describing = describing;
}
}
@Getter
@Setter
@ToString
@JsonNaming(PropertyNamingStrategy.KebabCaseStrategy.class)
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiModel("Pet")
public abstract class Pet {
@JsonProperty("name")
@ApiModelProperty(name = "name", value = "宠物昵称")
private String name;
@JsonProperty("serialNumber")
@ApiModelProperty(name = "serialNumber", value = "入店编号")
private Integer serialNumber;
@JsonProperty("age")
@ApiModelProperty(name = "age", value = "宠物年龄:1年02月")
private String age;
@JsonProperty("breed")
@ApiModelProperty(name = "breed", value = "宠物品种")
private String breed;
@JsonProperty("master")
@ApiModelProperty(name = "master", value = "主人")
private Master master;
public Pet(String name, Integer serialNumber, String age, String breed, Master master) {
this.name = name;
this.serialNumber = serialNumber;
this.age = age;
this.breed = breed;
this.master = master;
}
}
@Getter
@Setter
//@NoArgsConstructor
@ToString
@JsonNaming(PropertyNamingStrategy.KebabCaseStrategy.class)
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiModel("Master")
public class Master {
@JsonProperty("name")
@ApiModelProperty(name = "name", value = "主人姓名")
private String name;
@JsonProperty("age")
@ApiModelProperty(name = "age", value = "主人年龄")
private Integer age;
@JsonProperty("address")
@ApiModelProperty(name = "address", value = "主人在住地址")
private String address;
@JsonProperty("tel")
@ApiModelProperty(name = "tel", value = "主人联系电话")
private Long tel;
public Master(String name, Integer age, String address, Long tel) {
this.name = name;
this.age = age;
this.address = address;
this.tel = tel;
}
}
public class MemoryTest {
private static SecureRandom random = new SecureRandom();
@Test
public void testMemory() {
Set<Pet> allPets = new HashSet<>();
for (int i = 0; i < 30000; i++) {
Master master = new Master(random("姓名"), random.nextInt(30), random("地址"), random.nextLong());
Dog dog = new Dog(random("宠物"), i, random("1年02月"), random("哈士奇"), master);
dog.init(random("颜色"), random("2020年02月21日"), random("随机"), random("8:00-8:20 "), random("随机"));
allPets.add(dog);
}
ThreadUtils.waitSecond(30000);
}
private String random(String in) {
return in + random.nextLong();
}
}
浙公网安备 33010602011771号