网站首页 > 精选教程 正文
一、java基本类型长度及对应对象的字节长度
基本类型 | 长度(字节) | 对象长度(字节) |
int | 4 | 16 |
short | 2 | 16 |
long | 8 | 24 |
byte | 1 | 16 |
char | 1 | 16 |
float | 4 | 16 |
double | 8 | 24 |
System.out.println("Integer:" + ClassLayout.parseInstance(Integer.valueOf(122)).toPrintable());
输出
Integer:java.lang.Integer object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 64 22 00 f8 (01100100 00100010 00000000 11111000) (-134208924)
12 4 int Integer.value 122
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
二、对象内部组成
普通对象实例
对象头 | 身体 | 填充对齐 | |
mark | class指针 | 对象实际数据 | padding |
数组对象实例
对象头 | 身体 | 填充对齐 | ||
mark | class指针 | 数组Length | 对象实际数据 | padding |
注:数组实例对象中对象头多了一个记录数组长度的int类型对象,占4字节
对象头:
第一个部分mark,用于存储对象的运行时数据,比如哈希码(hashCode)、GC年龄分代、锁状态标志、线程持有的锁、偏向线程id、偏向时间戳等。 另外一部分class指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的。
对象头占用空间:
1、在32位系统下,存放class指针的空间大小是4字节,MarkWork是4字节,对象头为8字节。
2、在64位系统下,存放Class指针的空间大小是8字节,MarkWordk是8字节,对象头尾16字节。
3、在64位开启指针压缩的情况下(-XX:+UseCompressedOops),存放class指针的空间大小是4字节,markWord是8字节,对象头为12字节。
注:在开启指针压缩要求内存必须在4GB~32GB,因为32位指针寻址4GB,按8字节对齐, 4*8=32GB,按更大对齐可以寻址更大空间,但是浪费就更大了。
注:指针压缩不能压缩mark,指向非堆(Heap)的对象指针,局部变量、传参、返回值、NULL指针。
实例数据:
实例数据是对象存储的有效数据,也是程序代码中所定义的各种类型的字段内容,无论是从父类继承下来的,还是从子类中定义的,都需要记录起来。
对齐填充:
最后一块对齐填充空间并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用,这是由于HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说,就是对象的大小必须是8字节的整数
空对象:
(此处的空对象是指类中没有任何基础类型和引用, 不是对象 = null)
public class MyTest {
@Test
public void test(){
A a = new A();
System.out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
class A{
}
关闭指针压缩
(-XX:-UseCompressedOops)
类A没有值类型和引用类型 对象大小应该为 8(markword)+8(klass) 16byte
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) f0 e2 ba 17 (11110000 11100010 10111010 00010111) (398123760)
12 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
Instance size: 16 bytes
开启指针压缩
对象大小应该为 8(markword)+4(klass)因为对象大小最后要能被8整除,所以还要所以还要+4的的填充对齐 ,最后大小还是16byte
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) c8 16 01 20 (11001000 00010110 00000001 00100000) (536942280)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
注:64位系统内存大于4GB且小于32GB JVM默认开启指针压缩。
三、普通对象
public class MyTest {
@Test
public void test(){
A a = new A();
System.out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
class A{
int a;
float b;
long c;
String d;
}
关闭指针压缩:
对象大小应该是 8(markword)+8(Klass)+4(int)+4(float)+8(long)+8(string)(引用指针)40byte
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 58 e3 e9 17 (01011000 11100011 11101001 00010111) (401204056)
12 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
16 8 long A.c 0
24 4 int A.a 0
28 4 float A.b 0.0
32 8 java.lang.String A.d null
Instance size: 40 bytes
开启指针压缩:
对象大小应该是 8(markword)+4(Klass)+4(int)+4(float)+8(long)+4(string)(因为开启了指针压缩所以引用指针也是4byte)32byte
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) c8 16 01 20 (11001000 00010110 00000001 00100000) (536942280)
12 4 int A.a 0
16 8 long A.c 0
24 4 float A.b 0.0
28 4 java.lang.String A.d null
Instance size: 32 bytes
开启/关闭指针压缩的结果区别:
主要区别就是让原本占用8字节的指针缩小到4字节,另外未开启指针压缩时,上面提到的基本类型内存填充将会以8对齐,开启时以4字节对齐。但是对象尾部的填充不管是否开启都是以8字节对齐。
使用网上找的jar有个弊端
用这种方式只可以看到当前对象的大小,它所引用的对象实例大小是不会计算在里面的。如果要计算当前对象和对象引用的所有对象实例可以使用下面介绍的这个方法
可以使用jdk自带的jdk.nashorn.internal.ir.debug.ObjectSizeCalculator;可以评估出对象的大小。
System.out.println("Integer:" + ObjectSizeCalculator.getObjectSize(Integer.valueOf(122)));
猜你喜欢
- 2024-11-10 为什么28岁不能学java? 28岁开始学编程晚吗
- 2024-11-10 gc的年龄信息存储在什么地方? 年龄信息用什么数据类型存储
- 2024-11-10 JVM基础学习 jvm入门到精通
- 2024-11-10 Java-对象到底占多少个字节?计算规则是什么?
- 2024-11-10 浅谈JAVA中的基本变量 java常用变量
- 2024-11-10 大数据必学Java基础(十三):基本数据类型的转换
- 2024-11-10 Java码农35岁之后只能送外卖? 我的世界java
- 2024-11-10 这些Java基础知识,诸佬们都还记得嘛(学习,复习,面试都可)
- 2024-11-10 2021-01-03:java中,描述一下什么情况下,...
- 2024-11-10 零基础学Java之数据类型与变量(上集)
你 发表评论:
欢迎- 04-11Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- 04-11Java中你知道几种从字符串中找指定的字符的数量
- 04-11探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- 04-11Python字符串详解与示例(python字符串的常见操作)
- 04-11java正则-取出指定字符串之间的内容
- 04-11String s1 = new String("abc");这句话创建了几个字符串对象?
- 04-11java判断字符串中是否包含某个字符
- 04-11关于java开发中正确的发牌逻辑编写规范
- 最近发表
-
- Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- Java中你知道几种从字符串中找指定的字符的数量
- 探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- Python字符串详解与示例(python字符串的常见操作)
- java正则-取出指定字符串之间的内容
- String s1 = new String("abc");这句话创建了几个字符串对象?
- java判断字符串中是否包含某个字符
- 关于java开发中正确的发牌逻辑编写规范
- windows、linux如何后台运行jar(并且显示进程名)
- 腾讯大佬私人收藏,GitHub上最受欢迎的100个JAVA库,值得学习
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)