JDK版本1.8
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>8.11.2</version>
</dependency>
堆内存占用大小的工具类:RamUsageEstimator
//计算指定对象及其引用树上的所有对象的综合大小,单位字节
long RamUsageEstimator.sizeOf(Object obj)
//计算指定对象本身在堆空间的大小,单位字节
long RamUsageEstimator.shallowSizeOf(Object obj)
//计算指定对象及其引用树上的所有对象的综合大小,返回可读的结果,如:2KB
String RamUsageEstimator.humanSizeOf(Object obj)
点评:使用该第三方工具比较简单直接,主要依靠jvm本身环境、参数及CPU架构计算头信息,再依据数据类型的标准计算实例字段大小,计算速度很快,另外使用较方便。如果非要说这种方式有什么缺点的话,那就是这种方式计算所得的对象头大小是基于JVM声明规范的,并不是通过运行时内存地址计算而得,存在与实际大小不符的这种可能性。
package com.test;
import jdk.nashorn.internal.ir.debug.ObjectSizeCalculator;
import org.apache.lucene.util.RamUsageEstimator;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Test7 {
public static void main(String[] args) {
String s = "";
for (int i = 0; i < 20480; i++) {
s += "0";
}
System.out.println("实际大小:" + s.getBytes(StandardCharsets.UTF_8).length + " byte");
System.out.println("占用内存:" + RamUsageEstimator.sizeOf(s) + " byte");
System.out.println("占用内存:" + RamUsageEstimator.sizeOfObject(s) + " byte");
System.out.println("占用内存:" + ObjectSizeCalculator.getObjectSize(s) + " byte");//JDK自带工具
System.out.println();
Map<Object, Object> map = new HashMap<>();
for (int i = 0; i < 1024; i++) {
map.put(i, "0");
}
List<Object> list = new ArrayList<>();
map.put("list", list);
System.out.println("map占用内存:" + RamUsageEstimator.sizeOfMap(map) + " byte");
System.out.println("map占用内存:" + RamUsageEstimator.sizeOfObject(map) + " byte");
System.out.println("map占用内存:" + ObjectSizeCalculator.getObjectSize(map) + " byte");//JDK自带工具
System.out.println();
for (int i = 0; i < 1024; i++) {
list.add(0);
}
System.out.println("list占用内存:" + RamUsageEstimator.sizeOfCollection(list) + " byte");
System.out.println("map占用内存:" + RamUsageEstimator.sizeOfMap(map) + " byte");
System.out.println("map占用内存:" + RamUsageEstimator.sizeOfObject(map) + " byte");
System.out.println("map占用内存:" + ObjectSizeCalculator.getObjectSize(map) + " byte");//JDK自带工具
System.out.println();
Stu stu = new Stu();
System.out.println("stu占用内存:" + RamUsageEstimator.sizeOfObject(stu) + " byte");
System.out.println("stu占用内存:" + ObjectSizeCalculator.getObjectSize(stu) + " byte");//JDK自带工具
System.out.println();
stu.setList(list);
System.out.println("stu占用内存:" + RamUsageEstimator.sizeOfObject(stu) + " byte");
System.out.println("stu占用内存:" + ObjectSizeCalculator.getObjectSize(stu) + " byte");//JDK自带工具
System.out.println();
stu.setMap(map);
System.out.println("stu占用内存:" + RamUsageEstimator.sizeOfObject(stu) + " byte");
System.out.println("stu占用内存:" + ObjectSizeCalculator.getObjectSize(stu) + " byte");//JDK自带工具
System.out.println();
}
static class Stu {
private String name;
private List<Object> list;
private Map<Object, Object> map;
public void setName(String name) {
this.name = name;
}
public void setList(List<Object> list) {
this.list = list;
}
public void setMap(Map<Object, Object> map) {
this.map = map;
}
}
}
实际大小:20480 byte
占用内存:41000 byte
占用内存:41000 byte
占用内存:41000 byte
map占用内存:344232 byte
map占用内存:344216 byte
map占用内存:57592 byte
list占用内存:266280 byte
map占用内存:610472 byte
map占用内存:344216 byte
map占用内存:62528 byte
stu占用内存:256 byte
stu占用内存:24 byte
stu占用内存:256 byte
stu占用内存:5016 byte
stu占用内存:256 byte
stu占用内存:62552 byte
测试了,发现还是JDK自带的这个好用。ObjectSizeCalculator.getObjectSize
System.out.println("stu占用内存:" + ObjectSizeCalculator.getObjectSize(stu) + " byte");//JDK自带工具
————————————————
Java基本类型长度及对应对象的字节长度
基本类型 | 长度 | the size of an object |
---|---|---|
Int | 4 | 16 |
Short | 2 | 16 |
Long | 8 | 24 |
Byte | 1 | 16 |
Character | 1 | 16 |
Float | 4 | 16 |
Double | 8 | 24 |
java对象在内存中的结构
对象头(Mark Word)用于存储对象自身的运行时数据, 如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等等
Class对象指针:Class对象指针的大小也是4个字节,其指向的位置是对象对应的Class对象(其对应的元数据对象)的内存地址
对象实际数据:这里面包括了对象的所有成员变量,其大小由各个成员变量的大小决定,比如:byte和boolean是1个字节,short和char是2个字节,int和float是4个字节,long和double是8个字节,reference是4个字节
对齐:最后一部分是对齐填充的字节,按8个字节填充
Java Integer对象的内存结构
Java Array对象的内存结构
注意:数组对象和其他对象稍有不同,因为数据有一个长度length字段,所以在对象头后面还多了一个int类型的length字段,占4个字节,接下来才是数组中的数据