对象的内存布局
请解释下对象的创建过程?
- class loading
- class linking (verification ,prepare ,resolution)
- class initializing
- 申请对象内存
- 给成员变量赋默认值
- 调用构造方法 init
- 成员变量顺序赋初始值
- 执行构造方法语句
对象头存了啥?
对象大小(64位机)
观察虚拟机配置
java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=266664000 #JVM起始堆内存大小
-XX:MaxHeapSize=4266624000 #JVM最大堆内存大小
-XX:+UseCompressedClassPointers #默认打开Class指针压缩
-XX:+UseCompressedOops #默认打开普通对象指针压缩,Oops(ordinary object pointers)
-XX:+UseParallelGC #JVM默认使用的垃圾收集器(新生代:Parallel Scavenge,老年代:Parallel Old)
普通对象
-
对象头:markword 8
-
ClassPointer指针:-XX:+UseCompressedClassPointers 为4字节 不开启为8字节
-
实例数据
- 引用类型:-XX:+UseCompressedOops 为4字节 不开启为8字节
Oops Ordinary Object Pointers
- 引用类型:-XX:+UseCompressedOops 为4字节 不开启为8字节
-
Padding对齐,8的倍数
数组对象
- 对象头:markword 8
- ClassPointer指针同上
- 数组长度:4字节
- 数组数据
- 对齐 8的倍数
对象大小示例
Object大小: 头8 + ClassPoint (4 或 8) + Padding对其 = 16个字节
数组大小(空数组): 头8 + ClassPoint (4 或 8) + 数组长度 4 + Padding对其= 16 或 24
对象P: 32字节
private static class P {
//8 _markword
//4 _oop指针
int id; //4
String name; //4
int age; //4 byte b1; //1
byte b2; //1 Object o; //4
byte b3; //1}
实验
-
新建项目ObjectSize (1.8)
-
创建文件ObjectSizeAgent
package com.mashibing.jvm.agent; import java.lang.instrument.Instrumentation; public class ObjectSizeAgent { private static Instrumentation inst; public static void premain(String agentArgs, Instrumentation _inst) { inst = _inst; } public static long sizeOf(Object o) { return inst.getObjectSize(o); } }
-
src目录下创建META-INF/MANIFEST.MF
Manifest-Version: 1.0 Created-By: mashibing.com Premain-Class: com.mashibing.jvm.agent.ObjectSizeAgent
注意Premain-Class这行必须是新的一行(回车 + 换行),确认idea不能有任何错误提示
-
打包jar文件
-
在需要使用该Agent Jar的项目中引入该Jar包
project structure - project settings - library 添加该jar包 -
运行时需要该Agent Jar的类,加入参数:
-javaagent:C:\work\ijprojects\ObjectSize\out\artifacts\ObjectSize_jar\ObjectSize.jar
-
如何使用该类:
```java package com.mashibing.jvm.c3_jmm; import com.mashibing.jvm.agent.ObjectSizeAgent; public class T03_SizeOfAnObject { public static void main(String[] args) { System.out.println(ObjectSizeAgent.sizeOf(new Object())); System.out.println(ObjectSizeAgent.sizeOf(new int[] {})); System.out.println(ObjectSizeAgent.sizeOf(new P())); } private static class P { //8 _markword //4 _oop指针 int id; //4 String name; //4 int age; //4 byte b1; //1 byte b2; //1 Object o; //4 byte b3; //1 } }
Hotspot开启内存压缩的规则(64位机)
- 4G以下,直接砍掉高32位
- 4G - 32G,默认开启内存压缩 ClassPointers Oops
- 32G,压缩无效,使用64位
内存并不是越大越好(-)
IdentityHashCode的问题
当一个对象计算过identityHashCode之后,不能进入偏向锁状态
https://cloud.tencent.com/developer/article/1480590
https://cloud.tencent.com/developer/article/1484167
https://cloud.tencent.com/developer/article/1485795
https://cloud.tencent.com/developer/article/1482500
对象定位
•https://blog.csdn.net/clover_lily/article/details/80095580
- 句柄池
- 直接指针
T t = new T()
t 是怎么找到T的?
hotspot用的第二种,效率高一点.
有的JVM实现维护了一个中间指针,一个指向class,一个指向实际内存对象
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了