一、Java对象头
我们在编写一个Java类,编译后会生成.class文件,当类加载器将class文件加载到JVM时,会产生一个Klass类型的对象(c++),称为类描述元数据,存储在方法区中,即jdk1.8之后的元数据区。当使用new关键字创建对象时,就是根据类描述元数据Klass创建的对象oop,存储在堆中。每个Java对象都有相同的组成部分,就是对象头。
1.查看对象头的神器
jol(java object layout) java对象布局。
- 导入maven依赖:
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.14</version>
</dependency>
- 使用:
(1)创建一个简单的java类
public class User {
private String name;
private Integer age;
private boolean sex;
}
(2)输出对象布局信息
public static void main(String[] args) {
User user = new User();
log.debug("{}", ClassLayout.parseInstance(user).toPrintable());
}
输出结果:
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) 4f d7 00 f8 (01001111 11010111 00000000 11111000) (-134162609)
12 1 boolean User.sex false
13 3 (alignment/padding gap)
16 4 java.lang.String User.name null
20 4 java.lang.Integer User.age null
Instance size: 24 bytes
Space losses: 3 bytes internal + 0 bytes external = 3 bytes total
输出结果中类型描述为object header的即为对象头。
从图上可以看出,对象头所占的内存大小为12byte*8bit=96bit。本人使用的64位的jvm,正常对象头的大小应该是128bit。此处96bit的原因是jdk8版本默认开启了指针压缩,节约内存。如果想关闭指针压缩,可以修改vm参数:
-XX:-UseCompressedOops
2.对象头内部说明
我们已知64bit的jvm默认开启指针压缩的情况下,共占用96bit的内存。
其中64bit为Mark Word,32bit为Klass Word。
对象头内存图解
Mark Word的详细结构为:
Mark Word结构
二、Monitor的工作原理
Monitor工作原理- 刚开始Monitor中的Owner为null
- 当Thread-1执行synchronized(obj)时,就会将obj所关联的Monitor中的Owner置为Thread-1,Monitor中只能有一个Owner
- 在Thread-1为Owner的过程中,Thread-2、Thread-3、Thread-4也来执行synchronized(obj),就会进入Monitor的EntryList中,变成BLOCKED状态
- 当Thread-1执行完同步代码块中的代码时,会唤醒EntryList中等待的线程来竞争锁,竞争是非公平的
注: - synchronized必须是进入同一个对象的monitor才会有上述效果
- 不加synchronized的对象不会关联monitor监视器,不会遵从上述原则
网友评论