JVM及synchronize细节

一 类加载过程
1 加载Class文件
2 校验文件 例如文件的格式什么的
3 准备 给Class对象分配内存,类属性分配
4 解析 把文件将常量池中的符号引用替换为直接引用(内存地址)的过程
5 初始化 就是执行心态代码块给静态变量赋值

问题 Java中的引用,在多次GC后打印地址为什么不会变
答 java中的引用 其实是引用的句柄,通过这样的中间引用来保持地址变

二 锁的优化
1一个对象的组成有 数据头 mark_word,实例数据,和数据填充

在这里插入图片描述
问题,数据填充的意义在于?
答:64处理器一次最多能读8字节,而把对象填充为8字节的倍数,则能提高从内存读取数据的效率

mark_word 就是利用对象数据头来存储锁的信息,每一个mark_word关联一个monitor对象。并在获取锁时把mark_word的数据重置,unlock时数据置回。
锁的升级思想本质上就是为了应付不同的场景。
1偏向锁:方法只有一个线程访问
偏向锁加锁发生在偏向线程第一次进入同步块时,CAS原子操作尝试更新对象的Mark Word(偏向锁标志位为"1",记录偏向线程的ID)。
当有另一个线程来竞争锁的时候,就不能再使用偏向锁了,要膨胀为轻量级锁。
竞争线程尝试CAS更新对象头失败,会等待到全局安全点(此时不会执行任何代码)撤销偏向锁。
2轻量级锁:方法由多个线程访问,但是每个线程都能在时间片能执行完。
轻量级锁,是线程在栈帧中创建一个 lockrecord的数据块(包含一个对象指针和一个markword_区域(一个指向自己的地址和00轻量级锁的标志位)),线程首先让对象指针指向obj对象,然后查看obj中的mark_word是否指向的是自己,如果是则在增加一个lockrecord数据块(实现可重入),如果不是则采用cas来尝试,失败就膨胀为重量级锁。unlock的步骤也一样。
膨胀的具体过程就是把obj对象中的mark_word 指向一个mointor对象,然后尝试去获取锁。

三逃逸分析
逃逸分析就是JIT的一种优化
1 将堆分配转化为栈分配,如果方法中声明的对象没有暴露到外面,那么这个对象的可能就不会堆中分配,而是在栈中分配
2同步省略,如果一个synchronized方法,只有一个线程执行,那么字节码中就不会加上monitorentry monitorexit。比如在一个方法中使用了局部StringBuffer对象。
3离对象或标量替换,如果经过逃逸分析,发现一个对象不会被外界访问的话,那么经过JIT优化,就会把这个对象拆解成若干个其中包含的若干个成员变量来代替。这个过程就是标量替换。比如 声明一个局部变量,但是局部变量只有几个基础变量,那么久会直接生成这个基本量,而不是去堆上分配这个对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值