首页 > 其他 > 详细

对象头是个什么东东?

时间:2020-12-02 19:58:38      阅读:35      评论:0      收藏:0      [点我收藏+]

  对象头,顾名思义,就是对象的头。对象是实例化出来的,实例化的前提是必须有类这个模板。举个不大恰当的例子,人类就是个类,你我他就是人类实例化出来的对象。我们的头,自然就是对象头。我们的头有口鼻眼耳,对象头也有一些东西,主要包含两部分:Mark Word(标记字)和Class Pointer(类指针),如果是数组对象还得再加一项Array Length(数组长度)。

  对象头为啥要有这些东东?Mark Word用来标记运行时信息,Class Pointer用来指向生成该对象所在的类,Array Length告诉我们数组的长度。后两项简单易懂,最复杂的是这个Mark Word了,看下JVM的markWord.hpp是怎么规定它的:

// The markWord describes the header of an object.
//
// Bit-format of an object header (most significant first, big endian layout below):
//
//
32 bits: // -------- // hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object) // JavaThread*:23 epoch:2 age:4 biased_lock:1 lock:2 (biased object) // // 64 bits: // -------- // unused:25 hash:31 -->| unused_gap:1 age:4 biased_lock:1 lock:2 (normal object) // JavaThread*:54 epoch:2 unused_gap:1 age:4 biased_lock:1 lock:2 (biased object)

  它说markWord描述了对象头,采用大端点表示,markWord包含了哈希码、GC分代年龄、偏向锁、锁状态和用来滥竽充数的间隔位。32位和62位机器存储这些东东的大小各不相同。如果对象不再是普通对象,变成了一个偏向锁,那么markWord所含内容的哈希码就变成了持有锁的线程指针、偏向时间戳,其他不变。

  最后再说这个锁状态:

//  - the two lock bits are used to describe three states: locked/unlocked and monitor.
//
//    [ptr             | 00]  locked             ptr points to real header on stack
//    [header      | 0 | 01]  unlocked           regular object header
//    [ptr             | 10]  monitor            inflated lock (header is wapped out)
//    [ptr             | 11]  marked             used to mark an object

  00——轻量锁

  01——无锁,偏向锁就再往前一位看,0:无锁,1:偏向锁

  10——监视器锁(moniter),也就是重量锁

  11——GC标记

  好了,举例说明:

  1、pom.xml新增jar包:

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

  2、新增测试类:

/*
 * Licensed to Elasticsearch under one or more contributor
 * license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright
 * ownership. Elasticsearch licenses this file to you under
 * the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package com.wlf.springcloudgateway.concurrent;

import com.wlf.springcloudgateway.javabean.HelloWorld;
import org.openjdk.jol.info.ClassLayout;

import java.util.concurrent.TimeUnit;

public class ObjectMarkWord {

    public static void main(String[] args) throws InterruptedException {

        // 实例化对象
        HelloWorld helloWorld = HelloWorld.builder().name("wlf").build();

        // 1、普通对象,无锁
        System.out.println("普通对象:");
        printfObjMarkWord(helloWorld);

        // 2、实例化数组,打印数组对象信息,无锁
        System.out.println("数组对象:");
        String[] address = new String[]{"hangzhou", "nanjing", "shenzhen"};
        printfObjMarkWord(address);


        // 3、单线程首次加锁,轻量锁
        System.out.println("轻量锁:");
        new Thread(() -> {
            synchronized (helloWorld) {
                printfObjMarkWord(helloWorld);
            }
        }).start();

        TimeUnit.SECONDS.sleep(2);

        // 4、多个线程加锁,升级重量锁
        System.out.println("重量锁:");
        for (int i = 0; i < 2; i++) {
            new Thread(() -> {
                synchronized (helloWorld) {
                    printfObjMarkWord(helloWorld);
                }
            }).start();
        }
    }

    private static void printfObjMarkWord(Object obj) {
        System.out.println("-------------------------");
        System.out.println(ClassLayout.parseInstance(obj).toPrintable());
        System.out.println("-------------------------");

    }

}

  在跑之前给IDEA去掉指针压缩:Run -> Edit Configurations -> VM:options那一栏加上-XX:-UseCompressedOops

技术分享图片

 

 

 

  输出结果:

普通对象:
-------------------------
com.wlf.springcloudgateway.javabean.HelloWorld 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)                           88 49 0e 17 (10001000 01001001 00001110 00010111) (386812296)
     12     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     16     8   java.lang.String HelloWorld.name                           (object)
Instance size: 24 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

-------------------------
数组对象:
-------------------------
[Ljava.lang.String; 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)                           20 e9 dd 16 (00100000 11101001 11011101 00010110) (383641888)
     12     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     16     4                    (object header)                           03 00 00 00 (00000011 00000000 00000000 00000000) (3)
     20     4                    (alignment/padding gap)                  
     24    24   java.lang.String String;.<elements>                        N/A
Instance size: 48 bytes
Space losses: 4 bytes internal + 0 bytes external = 4 bytes total

-------------------------
轻量锁:
-------------------------
com.wlf.springcloudgateway.javabean.HelloWorld object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           60 f4 05 1a (01100000 11110100 00000101 00011010) (436597856)
      4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                    (object header)                           88 49 0e 17 (10001000 01001001 00001110 00010111) (386812296)
     12     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     16     8   java.lang.String HelloWorld.name                           (object)
Instance size: 24 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

-------------------------
重量锁:
-------------------------
com.wlf.springcloudgateway.javabean.HelloWorld object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           ca da 66 17 (11001010 11011010 01100110 00010111) (392616650)
      4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                    (object header)                           88 49 0e 17 (10001000 01001001 00001110 00010111) (386812296)
     12     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     16     8   java.lang.String HelloWorld.name                           (object)
Instance size: 24 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

-------------------------
-------------------------
com.wlf.springcloudgateway.javabean.HelloWorld object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           ca da 66 17 (11001010 11011010 01100110 00010111) (392616650)
      4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                    (object header)                           88 49 0e 17 (10001000 01001001 00001110 00010111) (386812296)
     12     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     16     8   java.lang.String HelloWorld.name                           (object)
Instance size: 24 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

-------------------------

Process finished with exit code 0

 

  我本机是64位的,所以markWord、class pointer、array length都是8字节:

技术分享图片

 

 

 

  至于有锁、无锁,看标黄的00、01,同一个对象的class pointer是一致的,从标黄处也能看出来。

对象头是个什么东东?

原文:https://www.cnblogs.com/wuxun1997/p/14075463.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!