无锁 | 偏向锁 | 轻量锁 | 重量锁 | GC |
---|---|---|---|---|
0 01 | 1 01 | 00 | 10 | 1 001 |
A.java
public class A {
}
JOLExample1.java
package com.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());
}
}
# 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.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
JOLExample.java
package com.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) throws NoSuchFieldException, IllegalAccessException {
//jvm的信息
A a= new A();
out.println("befor hash");
//没有计算HASHCODE之前的对象头
out.println(ClassLayout.parseInstance(a).toPrintable());
//JVM 计算的hashcode
out.println("jvm------------0x"+Integer.toHexString(a.hashCode()));
HashUtil.countHash(a);
//当计算完hashcode之后,我们可以查看对象头的信息变化
out.println("after hash");
out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
befor hash
# WARNING: Unable to attach Serviceability Agent. You can try again with escalated privileges. Two options: a) use -Djol.tryWithSudo=true to try with sudo; b) echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
com.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
jvm------------0x2e5c649
util‐‐‐‐‐‐‐‐‐‐‐0x2e5c649
after hash
com.layout.A object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 49 c6 e5 (00000001 01001001 11000110 11100101) (-439990015)
4 4 (object header) 02 00 00 00 (00000010 00000000 00000000 00000000) (2)
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
这种情况下,加锁的过程中是轻量锁。
package com.layout;
import org.openjdk.jol.info.ClassLayout;
import static java.lang.System.out;
public class JOLBiasLock {
static A a;
public static void main(String[] args) throws Exception {
// Thread.sleep(5000);
a= new A();
out.println("befor lock");
out.println(ClassLayout.parseInstance(a).toPrintable());
synchronized (a){
out.println("lock ing");
out.println(ClassLayout.parseInstance(a).toPrintable());
}
out.println("after lock");
out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
befor lock
# WARNING: Unable to attach Serviceability Agent. You can try again with escalated privileges. Two options: a) use -Djol.tryWithSudo=true to try with sudo; b) echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
com.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
lock ing
com.layout.A object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 98 19 04 0f (10011000 00011001 00000100 00001111) (251926936)
4 4 (object header) 00 70 00 00 (00000000 01110000 00000000 00000000) (28672)
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
after lock
com.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
lock ing 10011000是轻量级锁
在main方法中第一行加入Thread.sleep(5000);
lock ing 会是偏向锁
JVM延迟偏向锁是因为:如果不延迟,一上来就是偏向锁,假设程序后续还有线程调用,他会升级。jvm确定同步块中大部分代码都不是偏向锁,所以在启动的时候延迟。
A.java
package com.layout;
public class A {
int i=0;
// boolean flag =false;
public synchronized void parse(){
i++;
}
}
package com.layout;
public class BiasAndLightPerformance {
public static void main(String[] args) throws InterruptedException {
// Thread.sleep(5000); //打开就是偏向锁,不打开就是轻量级锁
A a = new A();
long start = System.currentTimeMillis();
//调用同步方法1000000000L 来计算1000000000L的++,对比偏向锁和轻量级锁的性能
//如果不出意外,结果灰常明显
for(int i =0;i<1000000000L;i++){
a.parse();
}
long end = System.currentTimeMillis();
System.out.println(String.format("%sms", end - start));
}
}
轻量级锁:16208ms
偏向锁:1768ms
重量级锁:
A.java
package com.layout;
public class A {
int i=0;
// boolean flag =false;
public synchronized void parse(){
i++;
HeavyLock.countDownLatch.countDown();
}
}
HeavyLock.java
package com.layout;
import java.util.concurrent.CountDownLatch;
public class HeavyLock {
static CountDownLatch countDownLatch = new CountDownLatch(1000000000);
public static void main(String[] args) throws InterruptedException {
final A a = new A();
long start = System.currentTimeMillis();
for (int i =0;i<2;i++){
new Thread(()->{
while (countDownLatch.getCount()>0){
a.parse();
}
}).start();
}
countDownLatch.await();
long end = System.currentTimeMillis();
System.out.println(String.format("%sms",end-start));
}
}
重量锁:50023ms
轻量锁 | 重量锁 | 偏向锁 |
---|---|---|
16208ms | 50023ms | 1768ms |
package com.layout;
import org.openjdk.jol.info.ClassLayout;
import static java.lang.System.out;
public class HeavyLockHead {
static A a;
public static void main(String[] args) throws Exception {
//Thread.sleep(5000);
a = new A();
out.println("befre lock");
out.println(ClassLayout.parseInstance(a).toPrintable());//无锁
Thread t1= new Thread(){
public void run() {
synchronized (a){
try {
Thread.sleep(5000);
System.out.println("t1 release");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t1.start();
Thread.sleep(1000);
out.println("t1 lock ing");
out.println(ClassLayout.parseInstance(a).toPrintable());//轻量锁
//此时t1线程把a锁住,并未释放。但是sync主线程这个时候过来竞争啊这把锁。所以锁会升级为重量锁
sync();
out.println("after lock");
out.println(ClassLayout.parseInstance(a).toPrintable());//重量锁
System.gc();
out.println("after gc()");
out.println(ClassLayout.parseInstance(a).toPrintable());/无锁---gc
}
public static void sync() throws InterruptedException {
synchronized (a){
System.out.println("t1 main lock");
out.println(ClassLayout.parseInstance(a).toPrintable());//重量锁
}
}
}
befre lock
# WARNING: Unable to attach Serviceability Agent. You can try again with escalated privileges. Two options: a) use -Djol.tryWithSudo=true to try with sudo; b) echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
com.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) 9f c1 00 f8 (10011111 11000001 00000000 11111000) (-134168161)
12 4 int A.i 0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
t1 lock ing
com.layout.A object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) b0 39 42 02 (10110000 00111001 01000010 00000010) (37894576)
4 4 (object header) 00 70 00 00 (00000000 01110000 00000000 00000000) (28672)
8 4 (object header) 9f c1 00 f8 (10011111 11000001 00000000 11111000) (-134168161)
12 4 int A.i 0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
t1 release
t1 main lock
com.layout.A object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 4a ad 00 e2 (01001010 10101101 00000000 11100010) (-503272118)
4 4 (object header) cd 7f 00 00 (11001101 01111111 00000000 00000000) (32717)
8 4 (object header) 9f c1 00 f8 (10011111 11000001 00000000 11111000) (-134168161)
12 4 int A.i 0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
after lock
com.layout.A object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 4a ad 00 e2 (01001010 10101101 00000000 11100010) (-503272118)
4 4 (object header) cd 7f 00 00 (11001101 01111111 00000000 00000000) (32717)
8 4 (object header) 9f c1 00 f8 (10011111 11000001 00000000 11111000) (-134168161)
12 4 int A.i 0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
after gc()
com.layout.A object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
1是gc标识
0 4 (object header) 09 00 00 00 (0000 1 001 00000000 00000000 00000000) (9)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 9f c1 00 f8 (10011111 11000001 00000000 11111000) (-134168161)
12 4 int A.i 0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
public class JOLExample11 {
static A a;
public static void main(String[] args) throws Exception {
//Thread.sleep(5000);
a = new A();
out.println("befre lock");
out.println(ClassLayout.parseInstance(a).toPrintable());
Thread t1= new Thread(){
public void run() {
synchronized (a){
try {
synchronized (a) {
System.out.println("before wait");
out.println(ClassLayout.parseInstance(a).toPrintable());
a.wait();
System.out.println(" after wait");
out.println(ClassLayout.parseInstance(a).toPrintable());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t1.start();
Thread.sleep(7000);
synchronized (a) {
a.notifyAll();
}
}
}
public class JOLExample8 {
static A a;
public static void main(String[] args) throws Exception {
Thread.sleep(5000);
a= new A();
a.hashCode();
out.println("befor lock");
out.println(ClassLayout.parseInstance(a).toPrintable());
synchronized (a){
out.println("lock ing");
out.println(ClassLayout.parseInstance(a).toPrintable());
}
out.println("after lock");
out.println(ClassLayout.parseInstance(a).toPrintable());
}
}