Java对象结构与内置锁

1. Java对象结构

先上图:
在这里插入图片描述

  1. 对象头

    Mark Word: 标记字,存储自身运行时的数据,例如GC标志位、哈希码、锁状态等信息
    Class Pointer: 类对象指针,存放方法区Class对象的地址,虚拟机通过这个指针来确定这个对象是哪个类的实例
    Array Length: 数组长度,如果对象是一个Java数组,那么此字段必须有,用于记录数组长度的数据,不是数组对象可以没有,可选字段

  2. 对象体

    对象体包含对象的实例变量(成员变量),用于成员属性值,包括父类的成员属性值。这部分内存按4字节对齐(4字节的整数倍)

  3. 对齐字节
    对齐字节也叫作填充对齐,其作用是用来保证Java对象所占内存字节数为8的倍数;对象头是8的倍数,当对象体实例变量数据不是8的倍数时,就需要进行字节填充使得整体是8的倍数

相关部分的作用:

  • Mark Word(标记字)字段主要用来表示对象的线程锁状态,另外还可以用来配合GC存放该对象的hashCode
  • Class Pointer(类对象指针)字段是一个指向方法区中Class信息的指针,意味着该对象可随时知道自己是哪个Class的实例
  • 对象体用于保存对象属性值,是对象的主体部分,占用的内存空间大小取决于对象的属性数量和类型
  • 对齐字节并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用

在32位JVM虚拟机中,Mark Word和Class Pointer这两部分都是32位的;在64位JVM虚拟机中,Mark Word和Class Pointer这两部分都是64位的


2. 代码实践

前提知识:

  • Mark Word长度:32位的JVM中是32位,64位的JVM中是64位
  • Class Pointer:32位的JVM中是32位,64位的JVM中是64位(开启指针压缩后是32位)
  • Array Length:32位

如何开启指针压缩:

-XX:+UseCompressedOops : 开启
-XX:-UseCompressedOops : 关闭

导入依赖:

<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.10</version>
</dependency>

1. 没有属性的对象

package innerlock;

import org.openjdk.jol.info.ClassLayout;

public class InnerLockTest {
	public static void main(String[] args) {
		InnerLockTest objInnerLockTest=new InnerLockTest();
		System.out.println(ClassLayout.parseInstance(objInnerLockTest).toPrintable());
	    
	}

}

关闭指针压缩
在这里插入图片描述

开启指针压缩

在这里插入图片描述

2. 带有基本类型属性的对象

package innerlock;

import org.openjdk.jol.info.ClassLayout;

public class InnerLockTest {
	//8种基本类型
	byte a=1;
	short b=2;
	int c=10;
	long d=100;
	float f=1.0f;
	double g=2.0;
	char h='#';
	boolean i=false;
	public static void main(String[] args) {
		InnerLockTest objInnerLockTest=new InnerLockTest();
		System.out.println(ClassLayout.parseInstance(objInnerLockTest).toPrintable());
	    
	}

}

关闭指针压缩
在这里插入图片描述

开启指针压缩
在这里插入图片描述

3. 带有引用类型的对象

package innerlock;

import org.openjdk.jol.info.ClassLayout;

public class InnerLockTest {
	String str1="hello";
	String str2="world";
	public static void main(String[] args) {
		InnerLockTest objInnerLockTest=new InnerLockTest();
		System.out.println(ClassLayout.parseInstance(objInnerLockTest).toPrintable());
	    
	}

}

关闭指针压缩

在这里插入图片描述

开启指针压缩
在这里插入图片描述

3. 数组类型对象

package innerlock;

import org.openjdk.jol.info.ClassLayout;

public class InnerLockTest {
	int a=1;
	public static void main(String[] args) {
		InnerLockTest []objInnerLockTest=new InnerLockTest[5];
		System.out.println(ClassLayout.parseInstance(objInnerLockTest).toPrintable());
	    
	}

}

关闭指针压缩
在这里插入图片描述

开启指针压缩

在这里插入图片描述对象数组中即使对象里面有实例属性,但是数组中依旧保存内存指针

所以对于数组对象而言,开启指针压缩的情况下(Mark Word: 8 Class Pointer:4 Array Length: 4),此时对象头刚好是8的倍数,不需要填充;不开启指针压缩的情况下(Mark Word: 8 Class Pointer:8 Array Length: 4),此时对象头需要填充, 整体是否需要填充取决于数组的大小,因为对象头已经是8的倍数,数组的每个元素是引用类型的4字节,偶数长度则不需要填充,奇数长度则需要填充。

如果是基本类型的数组,那么数组元素的大小取决于基本类型的大小,对象头的填充方式和对象数组一样


3. Mark Word的结构信息

Java内置锁的4种类型: 无锁,偏向锁,轻量级锁,重量级锁
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


4. 大小端问题

  • 大端模式是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中
  • 小端模式是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中

example:将十六进制数0X1234abcd写入以0x0000开始的内存地址中
在这里插入图片描述


5. 四种内置锁的概念

1. 无锁状态
Java对象刚创建时还没有任何线程来竞争,说明该对象处于无锁状态(无线程竞争它),这时偏向锁标识位是0,锁状态是01
在这里插入图片描述

2. 偏向锁状态
偏向锁是指一段同步代码一直被同一个线程所访问,那么该线程会自动获取锁,降低获取锁的代价。内置锁偏爱某个线程。 Mark Word会记录内置锁自己偏爱的线程ID,内置锁会将该线程当作自己的熟人
在这里插入图片描述

3. 轻量级锁状态
当有两个线程开始竞争这个锁对象时,情况就发生变化了,不再是偏向(独占)锁了,锁会升级为轻量级锁,两个线程公平竞争。
当锁处于偏向锁,又被另一个线程企图抢占时,偏向锁就会升级为轻量级
在这里插入图片描述

当A线程持有资源时,B线程过来竞争,发现A已经占有了,B不会立即阻塞挂起,而是进入一种“自旋”状态,等A释放后就立即获取锁。线程自旋是消耗CPU的,因此可以设置1个自旋时间上限,当自旋一定时间后还没有等到别的线程释放资源,就进入阻塞挂起状态,锁就会变成重量级锁。

4. 重量级锁
重量级锁会让其他申请的线程之间进入阻塞,性能降低。重量级锁也叫同步锁(synchronized就是重量级锁)

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodePanda@GPF

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值