当前位置: 首页 > news >正文

网站建站 公司/代写文案的软件

网站建站 公司,代写文案的软件,银行虚拟网站制作,优秀的国内企业网站java头的信息分析首先为什么我要去研究java的对象头呢?这里截取一张hotspot的源码当中的注释这张图换成人可读的表格如下意思是java的对象头在对象的不同状态下会有不同的表现形式,主要有三种状态,无锁状态、加锁状态、gc标记状态。那么我可以…

java头的信息分析

首先为什么我要去研究java的对象头呢?

这里截取一张hotspot的源码当中的注释

b638e58fddabebca10fe8ab904cab4fd.png

这张图换成人可读的表格如下

4a49d64e05ba5e12f9255992094a71bd.png

意思是java的对象头在对象的不同状态下会有不同的表现形式,主要有三种状态,无锁状态、加锁状态、gc标记状态。那么我可以理解java当中的取锁其实可以理解是给对象上锁,也就是改变对象头的状态,如果上锁成功则进入同步代码块。但是java当中的锁有分为很多种,从上图可以看出大体分为偏向锁、轻量锁、重量锁三种锁状态。这三种锁的效率完全不同、关于效率的分析会在下文分析,我们只有合理的设计代码,才能合理的利用锁、那么这三种锁的原理是什么?所以我们需要先研究这个对象头。

java对象的布局以及对象头的布局

1、JOL来分析java的对象布局

1 首先添加JOL的依赖2 3 org.openjdk.jol4 jol‐core5 0.96 

A.java

1 public class A {2 //没有任何字段3 }

JOLExample1.java

1 package com.luban.layout;2 import org.openjdk.jol.info.ClassLayout;3 import org.openjdk.jol.vm.VM;4 import static java.lang.System.out;56 public class JOLExample1 {7 public static void main(String[] args) throws Exception {8 out.println(VM.current().details());9 out.println(ClassLayout.parseClass(A.class).toPrintable());10 }11 }

运行结果

1 # Running 64‐bit HotSpot VM.2 # Using compressed oop with 0‐bit shift.3 # Using compressed klass with 3‐bit shift.4 # Objects are 8 bytes aligned.5 # Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]6 # Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]78 com.luban.layout.A object internals:9 OFFSET SIZE TYPE DESCRIPTION VALUE10 0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000)(1)11 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000)(0)12 8 4 (object header) 82 22 01 20 (10000010 00100010 00000001 00100000)(536945282)13 12 4 (loss due to the next object alignment)14 Instance size: 16 bytes15 Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

分析结果1

1 Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]对应:[Oop(OrdinaryObject Pointer), boolean, byte, char, short, int, float, long, double]大小

整个对象一共16B,其中对象头(Object header)12B,还有4B是对齐的字节(因为在64位虚拟机上对象的大小必须是8的倍数),由于这个对象里面没有任何字段,故而对象的实例数据为0B?两个问题

1、什么叫做对象的实例数据呢?

2、那么对象头里面的12B到底存的是什么呢?

首先要明白什么对象的实例数据很简单,我们可以在A当中添加一个boolean的字段,大家都知道boolean字段占1B,然后再看结果

A.java

1 public class A {2 //占一个字节的boolean字段3 boolean flag =false;4 }

运行结果2

1 # Running 64‐bit HotSpot VM.2 # Using compressed oop with 0‐bit shift.3 # Using compressed klass with 3‐bit shift.4 # Objects are 8 bytes aligned.5 # Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]6 # Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]78 com.luban.layout.A object internals:9 OFFSET SIZE TYPE DESCRIPTION VALUE10 0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000)(1)11 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000)(0)12 8 4 (object header) 82 22 01 20 (10000010 00100010 00000001 00100000)(536945282)13 12 1 boolean A.flag false14 13 3 (loss due to the next object alignment)15 Instance size: 16 bytes16 Space losses: 0 bytes internal + 3 bytes external = 3 bytes total

分析结果2

整个对象的大小还是没有改变一共16B,其中对象头(Object header)12B,boolean字段flag(对象的实例数据)占1B、剩下的3B就是对齐字节。由此我们可以认为一个对象的布局大体分为三个部分分别是对象头(Objectheader)、对象的实例数据字节对齐接下来讨论第二个问题,对象头为什么是12B?这个12B当中分别存储的是什么呢?(不同位数的VM对象头的长度不一样,这里指的是64bit的vm)关于java对象头的一些专业术语

http://openjdk.java.net/groups/hotspot/docs/HotSpotGlossary.html

首先引用openjdk文档当中对对象头的解释

object headerCommon structure at the beginning of every GC-managed heap object. (Every oop pointsto an object header.) Includes fundamental information about the heap object's layout,type, GC state, synchronization state, and identity hash code. Consists of two words. Inarrays it is immediately followed by a length field. Note that both Java objects and VM-internal objects have a common object header format

上述引用中提到一个java对象头包含了2个word,并且好包含了堆对象的布局、类型、GC状态、同步状态和标识哈希码,具体怎么包含的呢?又是哪两个word呢?

mark wordThe first word of every object header. Usually a set of bitfields including synchronizationstate and identity hash code. May also be a pointer (with characteristic low bit encoding)to synchronization related information. During GC, may contain GC state bits.

mark word为第一个word根据文档可以知他里面包含了锁的信息,

hashcode,gc信息等等,第二个word是什么呢?

klass pointerThe second word of every object header. Points to another object (a metaobject) whichdescribes the layout and behavior of the original object. For Java objects, the "klass"contains a C++ style "vtable".

klass word为对象头的第二个word主要指向对象的元数据。

f5ce386263c3f313acf151548879c904.png

假设我们理解一个对象头主要上图两部分组成(数组对象除外,数组对象的对象头还包含一个数组长度),那么一个java的对象头多大呢?我们从JVM的源码注释中得知到一个mark word一个是64bit,那么klass的长度是多少呢?

所以我们需要想办法来获得java对象头的详细信息,验证一下他的大小,验证一下里面包含的信息是否正确。

根据上述利用JOL打印的对象头信息可以知道一个对象头是12B,其中8B是mark word 那么剩下的4B就是klass word了,和锁相关的就是mark word了,那么接下来重点分析mark word里面信息在无锁的情况下markword当中的前56bit存的是对象的hashcode,那么来验证一下

java代码和运行结果:

1 public static void main(String[] args) throws Exception {2 A a= new A();3 out.println("befor hash");4 //没有计算HASHCODE之前的对象头5 out.println(ClassLayout.parseInstance(a).toPrintable());6 //JVM 计算的hashcode7 out.println("jvm‐‐‐‐‐‐‐‐‐‐‐‐"+Integer.toHexString(a.hashCode()));8 HashUtil.countHash(a);9 //当计算完hashcode之后,我们可以查看对象头的信息变化10 out.println("after hash");11 out.println(ClassLayout.parseInstance(a).toPrintable());1213 }1 befor hash2 com.luban.layout.A object internals:3 OFFSET SIZE TYPE DESCRIPTION VALUE4 0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000)(1)5 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000)(0)6 8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)7 12 1 boolean A.flag false8 13 3 (loss due to the next object alignment)9 Instance size: 16 bytes10 Space losses: 0 bytes internal + 3 bytes external = 3 bytes total1112 jvm‐‐‐‐‐‐‐‐‐‐‐‐0x6ae4099413 util‐‐‐‐‐‐‐‐‐‐‐0x6ae4099414 after hash15 com.luban.layout.A object internals:16 OFFSET SIZE TYPE DESCRIPTION VALUE17 0 4 (object header) 01 94 09 e4 (00000001 10010100 00001001 11100100)(‐469134335)18 4 4 (object header) 6a 00 00 00 (01101010 00000000 00000000 00000000)(106)19 8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000)(536920387)20 12 1 boolean A.flag false21 13 3 (loss due to the next object alignment)22 Instance size: 16 bytes23 Space losses: 0 bytes internal + 3 bytes external = 3 bytes total242526 Process finished with exit code 0

http://tool.oschina.net/hexconvert/ 进制转换

1 package com.luban.layout;2 import sun.misc.Unsafe;3 import java.lang.reflect.Field;45 public class HashUtil {6 public static void countHash(Object object) throws NoSuchFieldException,IllegalAccessException {7 // 手动计算HashCode8 Field field = Unsafe.class.getDeclaredField("theUnsafe");9 field.setAccessible(true);10 Unsafe unsafe = (Unsafe) field.get(null);11 long hashCode = 0;12 for (long index = 7; index > 0; index‐‐) {13 // 取Mark Word中的每一个Byte进行计算14 hashCode |= (unsafe.getByte(object, index) & 0xFF) << ((index ‐ 1) *8);15 }16 String code = Long.toHexString(hashCode);17 System.out.println("util‐‐‐‐‐‐‐‐‐‐‐0x"+code);1819 }20 }

分析结果3:

1-----9行是没有进行hashcode之前的对象头信息,可以看到1-7B的56bit没有值,打印完hashcode之后16----21行就有值了,为什么是1-7B,不是0-6B呢?因为是小端存储。其中12行是我们通过hashcode方法打印的结果,13行是我根据1-7B的信息计算出来的hashcode,所以可以确定java对象头当中的mark work里面的后七个字节存储的是hashcode信息,那么第一个字节当中的八位分别存的就是分带年龄、偏向锁信息,和对象状态,这个8bit分别表示的信息如下图(其实上图也有信息),这个图会随着对象状态改变而改变,下图是无锁状态下

9446c50d2d241f6e68d453fdf1cd7f8b.png

关于对象状态一共分为五种状态,分别是无锁、偏向锁、轻量锁、重量锁、GC标记,那么2bit,如何能表示五种状态(2bit最多只能表示4种状态分别是:

00,01,10,11),jvm做的比较好的是把偏向锁和无锁状态表示为同一个状态,然后根据图中偏向锁的标识再去标识是无锁还是偏向锁状态。什么意思呢?写个代码分析一下,在写代码之前我们先记得无锁状态下的信息00000001,然后写一个偏向锁的例子看看结果

Java代码和输出结果:

1 package com.luban.layout;2 import org.openjdk.jol.info.ClassLayout;3 import static java.lang.System.out;45 public class JOLExample2 {6 static A a;7 public static void main(String[] args) throws Exception {8 //Thread.sleep(5000);9 a = new A();10 out.println("befre lock");11 out.println(ClassLayout.parseInstance(a).toPrintable());12 sync();13 out.println("after lock");14 out.println(ClassLayout.parseInstance(a).toPrintable());15 }1617 public static void sync() throws InterruptedException {18 synchronized (a){19 System.out.println("我也不知道要打印什么");20 }2122 }23 }
1 befre lock2 com.luban.layout.A object internals:3 OFFSET SIZE TYPE DESCRIPTION VALUE4 0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000)(1)5 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000)(0)6 8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)7 12 1 boolean A.flag false8 13 3 (loss due to the next object alignment)9 Instance size: 16 bytes10 Space losses: 0 bytes internal + 3 bytes external = 3 bytes total1112 我也不知道要打印什么13 after lock14 com.luban.layout.A object internals:15 OFFSET SIZE TYPE DESCRIPTION VALUE16 0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000)(1)17 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000)(0)18 8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000)(536920387)19 12 1 boolean A.flag false20 13 3 (loss due to the next object alignment)

分析结果4

上面这个程序只有一个线程去调用sync方法,故而讲道理应该是偏向锁,但是你会发现输出的结果(第一个字节)依然是00000001和无锁的时候一模一样,其实这是因为虚拟机在启动的时候对于偏向锁有延迟,比如把上述代码当中的睡眠注释掉结果就会不一样了,结果会变成00000101当然为了方便测试我们可以直接通过JVM的参数来禁用延迟-XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0,想想为什么偏向锁会延迟?(除了这8bit,其他bit存储了线程信息和epoch,这里不截图了),需要注意的afterlock,退出同步后依然保持了偏向信息

885e81811513190a2d16883e8237cf5e.png

性能对比偏向锁和轻量级锁:

1 package com.luban.layout;2 public class A {3 int i;4 public synchronized void parse(){5 i++;6 }7 }1 package com.luban.layout;2 import org.openjdk.jol.info.ClassLayout;3 import static java.lang.System.out;4 //‐XX:BiasedLockingStartupDelay=20000 ‐XX:BiasedLockingStartupDelay=05 public class JOLExample3 {6 public static void main(String[] args) throws Exception {7 A a = new A();8 long start = System.currentTimeMillis();9 //调用同步方法1000000000L 来计算1000000000L的++,对比偏向锁和轻量级锁的性能10 //如果不出意外,结果灰常明显11 for(int i=0;i<1000000000L;i++){12 a.parse();13 }14 long end = System.currentTimeMillis();15 System.out.println(String.format("%sms", end ‐ start));1617 }1819 }

那么问题来了,什么是轻量级锁呢?工作原理是什么呢?为什么比偏向锁慢?轻量级锁尝试在应用层面解决线程同步问题,而不触发操作系统的互斥操作,轻量级锁减少多线程进入互斥的几率,不能代替互斥

首先看一下轻量级锁的对象头

1 package com.luban.layout;2 import org.openjdk.jol.info.ClassLayout;3 import static java.lang.System.out;45 public class JOLExample5 {6 static A a;7 public static void main(String[] args) throws Exception {8 a = new A();9 out.println("befre lock");10 out.println(ClassLayout.parseInstance(a).toPrintable());11 sync();12 out.println("after lock");13 out.println(ClassLayout.parseInstance(a).toPrintable());14 }1516 public static void sync() throws InterruptedException {17 synchronized (a){18 out.println("lock ing");19 out.println(ClassLayout.parseInstance(a).toPrintable());20 }21 }22 }

性能对比轻量对比重量:

1 package com.luban.layout;23 import java.util.concurrent.CountDownLatch;45 public class JOLExample4 {6 static CountDownLatch countDownLatch = new CountDownLatch(1000000000);7 public static void main(String[] args) throws Exception {8 final A a = new A();910 long start = System.currentTimeMillis();1112 //调用同步方法1000000000L 来计算1000000000L的++,对比偏向锁和轻量级锁的性能13 //如果不出意外,结果灰常明显14 for(int i=0;i<2;i++){15 new Thread(){16 @Override17 public void run() {18 while (countDownLatch.getCount() > 0) {19 a.parse();20 }21 }22 }.start();23 }24 countDownLatch.await();25 long end = System.currentTimeMillis();26 System.out.println(String.format("%sms", end ‐ start));2728 }2930 }
c0cd52a0ae171e01fbd29c842ec43dde.png

关于重量锁首先看对象头

1 package com.luban.layout;2 import org.openjdk.jol.info.ClassLayout;3 import static java.lang.System.out;45 public class JOLExample6 {6 static A a;7 public static void main(String[] args) throws Exception {8 //Thread.sleep(5000);9 a = new A();10 out.println("befre lock");11 out.println(ClassLayout.parseInstance(a).toPrintable());1213 Thread t1= new Thread(){14 public void run() {15 synchronized (a){16 try {17 Thread.sleep(5000);18 System.out.println("t1 release");19 } catch (InterruptedException e) {20 e.printStackTrace();21 }22 }23 }24 };25 t1.start();26 Thread.sleep(1000);27 out.println("t1 lock ing");28 out.println(ClassLayout.parseInstance(a).toPrintable());29 sync();30 out.println("after lock");31 out.println(ClassLayout.parseInstance(a).toPrintable());3233 System.gc();34 out.println("after gc()");35 out.println(ClassLayout.parseInstance(a).toPrintable());36 }3738 public static void sync() throws InterruptedException {39 synchronized (a){40 System.out.println("t1 main lock");41 out.println(ClassLayout.parseInstance(a).toPrintable());42 }43 }44 }

需要注意的是如果对象已经计算了

hashcode就不能偏向了

1 package com.luban.layout;2 import org.openjdk.jol.info.ClassLayout;3 import static java.lang.System.out;45 public class JOLExample8 {6 static A a;7 public static void main(String[] args) throws Exception {89 Thread.sleep(5000);10 a = new A();11 a.hashCode();12 out.println("befre lock");13 out.println(ClassLayout.parseInstance(a).toPrintable());1415 Thread t1= new Thread(){16 public void run() {17 synchronized (a){18 try {19 synchronized (a) {20 System.out.println("lock ed");21 out.println(ClassLayout.parseInstance(a).toPrintable());22 }23 } catch (Exception e) {24 e.printStackTrace();25 }26 }27 }28 };29 t1.start();3031 }32 }
http://www.jmfq.cn/news/5172067.html

相关文章:

  • 网站程序复制/合肥seo建站
  • 莱芜专注搜狗推广/seo关键词排名优化技巧
  • 主要网站维护软件/杭州seo网站建设
  • 专业做网站+上海/新网站推广最直接的方法
  • 阿里巴巴有没有帮做网站的公司/东莞网站建设最牛
  • 网站设计趋势/googlechrome浏览器
  • h5美食制作网站模板下载/平台推广文案
  • 郑州郑州网站建设河南做网站公司哪家好/英文谷歌优化
  • 合肥浦发建设集团网站/如何给公司网站做推广
  • 沙井网站推广/东莞企业网站排名
  • 东莞建设企业网站/有没有可以代理推广的平台
  • 如何自己做资源网站/seo在线优化工具
  • 互助网站开发/珠海网站建设
  • wordpress建设的是模板网站吗/百度推广是怎么做的
  • 网站建设方案云盘/注册域名后怎么建网站
  • 长沙南站建站/百度指数在线查询
  • 做网站接雕塑业务/网站推广优化教程
  • 一般做个网站多少钱/裤子seo标题优化关键词
  • 乐山网站建设/网络营销的基本方式有哪些
  • 南城网站建设公司咨询/正规seo大概多少钱
  • 小公司让我用织梦做网站/外贸网络营销
  • 带数据库的网站做/泉州seo按天计费
  • 小狗做爰网站/北京seo费用是多少
  • 高端网站设计培训机构/沈阳seo优化新势力
  • 唯品会网站建设数据安全分析/免费推广的app有哪些
  • 买什么样的主机(用来建网站的)支持下载/小程序推广平台
  • 广州网站建设怎么做/百度词条
  • 网站的推广方案有哪些/网址生成短链接
  • 网站外包维护一年多少钱/网站建设合同
  • 怎么做公司网站需要什么科目/建站系统