# 相关面试题

# 题目及答案

  1. 请解释一下对象的创建过程

    image-20201110223226913

    其他答案:

    一个对象的创建过程包含两个过程:初始化和实例化

    初始化是指我们在使用一个对象时,JVM首先会检查相关类型是否已经加载并初始化,如果没有,则JVM立即进行加载并调用类构造器完成类的初始化。在类初始化过程中或初始化完毕后,根据具体情况才会去对类进行实例化。

    实例化时候,java虚拟机就会为其分配内存, 用于存放自己及其从父类继承过来的实例变量。在为这些实例变量分配内存的同时,这些实例变量先会被赋予默认值(零值)。在内存分配完成之后,Java虚拟机才会对新创建的对象赋予初始值。

  2. 对象在内存中的存储布局?

    内容请参照对象布局

  3. 对象头具体包括什么?

    image-20201110233155019

    image-20201110233357940

  4. 对象怎么定位?

    请查看对象定位

  5. 对象怎么分配?

  6. Object o = new Object() 在内存中占用多少个字节?

    内容请参照普通对象

    头对象 8 + ClassPointer 4 + Padding

# 对象大小(64位机)

# 观察虚拟机配置

通过命令 java -XX:+PrintCommandLineFlags -version 可以观察虚拟机的配置.

# 对象布局

关于对象布局, 分为普通对象和数组对象,

# 普通对象

  1. 对象头

    在HotSport 中称为 markword 8字节

  2. ClassPointer

    ClassPointer (class 的指针) 指向 class 对象. 如 T t = new T(); 中, 这个指针指向的是 t.class

    -XX:+UseCompressedClassPointers 开启为4字节 不开启为8字节

    默认

  3. 实例数据

    实例数据指的是对象内部的属性数据

    引用类型:-XX:+UseCompressedOops 为4字节 不开启为8字节 (默认打开) Oops: Ordinary Object Pointers 普通对象指针 (默认打开)

  4. Padding 对齐

    系统在读的时候会按块读取, 这个对齐的块是8的倍数

# 数组对象

  1. 对象头:markword 8

  2. ClassPointer指针同上

  3. 数组长度:4字节

    数组的长度信息, 比普通对象多 4 个字节

  4. 数组数据

  5. 对齐 8的倍数

# 实验

Agent 可以在虚拟机 load .class 文件的过程中截获信息, 同时也可以对其进行修改. 当然也可以读取其相关的信息.

  1. 新建项目ObjectSize (1.8)

  2. 创建文件ObjectSizeAgent

    package com.mashibing.jvm.agent;
    
    import java.lang.instrument.Instrumentation;
    
    public class ObjectSizeAgent {
        private static Instrumentation inst;
    
        public static void premain(String agentArgs, Instrumentation _inst) {
            inst = _inst;
        }
    
        public static long sizeOf(Object o) {
            return inst.getObjectSize(o);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
  3. src目录下创建META-INF/MANIFEST.MF

    Manifest-Version: 1.0
    Created-By: mashibing.com
    # 第三项必须要有
    Premain-Class: com.mashibing.jvm.agent.ObjectSizeAgent
    
    1
    2
    3
    4

    注意Premain-Class这行必须是新的一行(回车 + 换行),确认idea不能有任何错误提示

  4. 打包jar文件

  5. 在需要使用该Agent Jar的项目中引入该Jar包 project structure - project settings - library 添加该jar包

  6. 运行时需要该Agent Jar的类,加入参数:

    -javaagent:C:\work\ijprojects\ObjectSize\out\artifacts\ObjectSize_jar\ObjectSize.jar
    
    1
  7. 如何使用该类:

    package com.mashibing.jvm.c3_jmm;
       
       import com.mashibing.jvm.agent.ObjectSizeAgent;
       
    public class T03_SizeOfAnObject {
      public static void main(String[] args) {
        System.out.println(ObjectSizeAgent.sizeOf(new Object()));
        System.out.println(ObjectSizeAgent.sizeOf(new int[] {}));
        System.out.println(ObjectSizeAgent.sizeOf(new P()));
      }
    
      private static class P {
        //8 _markword
        //4 _oop指针
        int id;         //4
        String name;    //4 -XX +UseCompressedOops
        int age;        //4
    
        byte b1;        //1
        byte b2;        //1
    
        Object o;       //4
        byte b3;        //1
    
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26

# Hotspot开启内存压缩的规则(64位机)

  1. 4G以下,直接砍掉高32位
  2. 4G - 32G,默认开启内存压缩 ClassPointers Oops
  3. 32G,压缩无效,使用64位 内存并不是越大越好(^-^)

# IdentityHashCode的问题

回答白马非马的问题:

当一个对象计算过identityHashCode之后,不能进入偏向锁状态

https://cloud.tencent.com/developer/article/1480590 https://cloud.tencent.com/developer/article/1484167

https://cloud.tencent.com/developer/article/1485795

https://cloud.tencent.com/developer/article/1482500

# 对象定位

https://blog.csdn.net/clover_lily/article/details/80095580

  1. 句柄池

    对象的指针指向句柄池, GC 的时候效率高, 但是找对象的效率较低

    1. 句柄池中一个指针指向对象
    2. 另一个指针指向 .class 对象
  2. 直接指针

    GC 的时候效率低, 但是找到对象的效率较低

    1. 直接指向对象
上次更新时间: 2020/11/12 上午1:35:10