栈:基本数据类型(8个) 执行上下文 操作指令 对象的引用 main() (数据共享,线程私有)
堆:对象(new person())线程共享
方法区:类(对象的抽象模板) 线程共享
java对象的布局:
1.对象头--固定存在 synchronized用的锁就存在java对象头里面
2.实例数据---不固定,取决于定义的大小(过大过多,内存溢出)
3.数据对齐(填充数据) 例如64bit的jvm规定对象大小是8的整数倍,如boolean flag = false;//原本是1byte,但是虚拟机分配时还是会分配8byte(1byte实例数据+7byte填充数据)
实际:头(12byte)+boolean(1byte)=13byte,不是8的倍数 ,加上3byte,一共分配了16byte的空间
证明:
//Parse Instance解析实例,用sout输出到控制台可看Java对象布局:
System.out.println(ClassLayout.parseInstance(j).toPrintable());
问题1:jol运行不支持
原因:用的是J9(是jvm的具体实现),详细关系见:Eclipse OpenJ9与Eclipse OMR简介 - 知乎
什么是java对象头由什么组成:
结论:synchronized java对象头--mark word= 32 bit =4 byte(32位jvm)
实验:96bit = 12byte(64位jvm)
组成结构:
Mark Word+Klass pointer /Class Metadata Address(类的模板信息地址,如Test t = new Test()之中的Test的地址)
1.理解JVM,HotSpot,openjdk之间的关系
JVM------标准/规范 -------------规定了对象头由什么组成
HotSpot------产品/实现(基于openjdk,8成用的openjdk开源代码,2成未开源商用代码)
openjdk---------项目(c++)------>编译成exe就是hotspot
openjdk里包含hotspot。
对象头:每个gc管理的堆对象开头的公共结构。(每个oop,即指针都指向一个对象头)包括堆对象的布局,类型(储存类的模板信息地址),GC状态(ps.为什么在gc中survivor到老年代需要重复15次from到to,age=15,因为4bit最大表示10进制2^4=16),同步状态和标识哈希码的基本信息。由两个属性组成,在数组中,他后面紧跟着一个长度字段,注意,java对象和jvm内部对象都有一个通用的对象头格式。
对象状态:使用synchronized关键字时java对象一共分为几种?
1.无状态(刚new出来)
2.偏向锁(刚上了锁,只有一个线程持有该对象)
3.轻量锁
4.重量锁
5.gc标记
128bit也有可能是96bit(如果开启了指针压缩,原本klass word要用64bit存压缩到32bit)
各状态下对象头占用情况:
biased_lock------偏向锁的偏向信息
lock------------------锁的状态(对象状态)
其中lock占2位最多能表示4种状态(00,01,10,11),但是对象状态有5种,所以需要配合偏向信息来表示