计算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();
}
}
posted @ 2020-05-15 16:23  qsz_052  阅读(207)  评论(0)    收藏  举报