# 如何计算对象大小
1. 搞清楚Java对象的布局结构
2. 借助`jol-core`包来打印对象
3. 引用的指针压缩
## 对象布局
![](https://img.kancloud.cn/ce/c1/cec1a91e96673b1c679c0b6562b621f8_1938x1098.png)
## Java对象布局(Java Object Layout)
### String对象例子
![](https://img.kancloud.cn/5e/35/5e356e34a9e40ad15625d059b97b2a4b_3664x844.png)
### int[]数组对象例子
![](https://img.kancloud.cn/04/21/042133c524d818fb5327b9647c812b7b_3716x1484.png)
## 引用的指针压缩
### JVM内存寻址最大内存是多少?
~~~
// 打印jvm的详细信息
System.out.println(VM.current().details());
~~~
```
# Running 64-bit HotSpot VM. // 64位hotSpot虚拟机
# Using compressed oop with 3-bit shift. // 对象压缩 3位无符号右移
# Using compressed klass with 3-bit shift. // 类型指针压缩 3为无符号右移
# Objects are 8 bytes aligned. // 对象按8字节对齐
```
对象按8字节对齐,且jvm的引用占4个字节,能表示2^32=4G * 8 = 32G的物理内存。
![](https://img.kancloud.cn/63/af/63afe676ba86ed88ec44e989693c5337_1780x758.png)
### 不启用指针压缩
采用8字节(64位)存储真实内存地址,比之前采用4字节(32位)压缩存储地址带来的问题:
1. 增加了GC开销:64位对象引用需要占用更多的堆空间,留给其他数据的空间将会减少,从而加快了GC的发生,更频繁的进行GC。
2. 降低CPU缓存命中率:64位对象引用增大了,CPU能缓存的oop将会更少,从而降低了CPU缓存的效率。
### 启用指针压缩
* `-XX:+UseCompressedOops` 开启指针压缩,jdk6之后默认开启。
* `-XX:+PrintFlagsFinal` 打印jvm参数,可以用来验证检查环境内的参数配置生效情况。
* 内存大于32GB时,开启指针压缩的参数会失效!
## 总结
对象大小 = 对象头字节 + 实例数据字节 + 填充字节
## 参考资料
* 周志明 * 《深入理解Java虚拟机》
- 面试突击
- Java虚拟机
- 认识字节码
- 000Java发展历史
- 000Macos10.15.7上编译OpenJDK8u
- 001熟悉Java内存区域
- 002熟悉HotSpot中的对象
- 003Java如何计算对象大小
- 004垃圾判定算法与4大引用
- 005回收堆和方法区中对象
- 006垃圾收集算法
- 007HotSpot虚拟机垃圾算法实现篇1
- 007HotSpot虚拟机垃圾算法实现篇2
- 007HotSpot虚拟机垃圾算法实现篇3
- 008垃圾收集器
- 009内存分配与回收策略
- 010Java虚拟机相关工具
- 011调优案例分析
- 012一次IDEA的启动速度调优
- 013类文件Class的结构
- 014熟悉字节码指令
- 015类加载机制(过程)
- 016类加载器
- IDEA的JVM参数
- Java基础
- Java自动装箱与拆箱
- Java基础数据类型
- Java方法的参数传递
- Java并发
- 001走入并行的世界
- 002并行程序基础
- 003熟悉Java内存模型JMM
- 004Java并发之volatile关键字
- 005线程池入门到精通
- 006Java多线程间的同步控制方法
- 007Java维基准测试框架JMH
- 008Java并发容器
- 009Java的线程实现
- 010Java关键字synchronized
- 011一些并行模式的熟悉
- 单例模式和不变模式
- 生产者消费者模式
- Future模式
- 012一些并行算法的熟悉
- 面试总结
- 长亮一面