java头信息分析
下面这张图是我截取hotspot源码当中的注释转化而成
意思是java的对象头在对象的不同状态下会有不同的表现形式,主要有三种状态,无锁状态、枷锁状态、gc标记状态。那么我们可以理解java当中的取锁其实可以理解是给对象上锁,也就是改变对象头的状态,如果上锁成功则进入同步代码块,但是java当中的锁又分为很多种,从上图可以看出大体分为偏向锁、轻量锁、重量锁三种锁状态。这三种锁的效率完全不同,想要弄清楚这三种锁的原理,所以我们性需要先研究这个对象头
java对象的布局及对象头的布局
使用JOL来分析java对象的布局,添加JOL依赖
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.8</version>
</dependency>
A.java
public class A {
//没有任何字段
}
JOLExample1.java
package com.luban.layout;
import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.vm.VM;
import static java.lang.System.out;
public class JOLExample1 {
static A a = new A();
public static void main(String[] args) {
//jvm的信息
out.println(VM.current().details());
out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
运行的结果为:
D:\soft\java\jdk1.8.0_161\bin\java.exe "-javaagent:D:\soft\idea\IntelliJ IDEA 2018.3.5\lib\idea_rt.jar=62006:D:\soft\idea\IntelliJ IDEA 2018.3.5\bin" -Dfile.encoding=UTF-8 -classpath D:\soft\java\jdk1.8.0_161\jre\lib\charsets.jar;D:\soft\java\jdk1.8.0_161\jre\lib\deploy.jar;D:\soft\java\jdk1.8.0_161\jre\lib\ext\access-bridge-64.jar;D:\soft\java\jdk1.8.0_161\jre\lib\ext\cldrdata.jar;D:\soft\java\jdk1.8.0_161\jre\lib\ext\dnsns.jar;D:\soft\java\jdk1.8.0_161\jre\lib\ext\jaccess.jar;D:\soft\java\jdk1.8.0_161\jre\lib\ext\jfxrt.jar;D:\soft\java\jdk1.8.0_161\jre\lib\ext\localedata.jar;D:\soft\java\jdk1.8.0_161\jre\lib\ext\nashorn.jar;D:\soft\java\jdk1.8.0_161\jre\lib\ext\sunec.jar;D:\soft\java\jdk1.8.0_161\jre\lib\ext\sunjce_provider.jar;D:\soft\java\jdk1.8.0_161\jre\lib\ext\sunmscapi.jar;D:\soft\java\jdk1.8.0_161\jre\lib\ext\sunpkcs11.jar;D:\soft\java\jdk1.8.0_161\jre\lib\ext\zipfs.jar;D:\soft\java\jdk1.8.0_161\jre\lib\javaws.jar;D:\soft\java\jdk1.8.0_161\jre\lib\jce.jar;D:\soft\java\jdk1.8.0_161\jre\lib\jfr.jar;D:\soft\java\jdk1.8.0_161\jre\lib\jfxswt.jar;D:\soft\java\jdk1.8.0_161\jre\lib\jsse.jar;D:\soft\java\jdk1.8.0_161\jre\lib\management-agent.jar;D:\soft\java\jdk1.8.0_161\jre\lib\plugin.jar;D:\soft\java\jdk1.8.0_161\jre\lib\resources.jar;D:\soft\java\jdk1.8.0_161\jre\lib\rt.jar;D:\workspace\luban\concurrency(1)\target\classes;D:\repository\org\openjdk\jol\jol-core\0.8\jol-core-0.8.jar com.luban.layout.JOLExample1
# Running 64-bit HotSpot VM.
# Using compressed oop with 3-bit shift.
# Using compressed klass with 3-bit shift.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
com.luban.layout.A 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) 43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
Process finished with exit code 0
第一个字节当中的八位分别存的就是分带年龄、偏向锁信息,和对象状态,这个8bit分别表示的信息如下图(其实上图也有信息),这个图会随着对象状态改变而改变,下图是无锁状态下
定义 | 对象头第一个字节 | 性能对比(10亿) | 备注 | |
无锁 | 未使用锁 | 00000001 | - | |
偏向锁 | -XX:BiasedLockingStartupDelay=0 这个参数可将JVM偏向锁延时设置为0,单线程用锁就是偏向锁 | 00000101 | 8255ms | 如果对象已经计算了hashcode就不能偏向了 |
轻量锁 | 两个及两个以上的线程之间未发生资源竞争 | 00001000 | 27942ms | |
重量锁 | 两个及两个以上的线程竞争锁资源时膨胀为重量锁 | 11011010 | 39274ms |