JVM_4 对象

212 阅读2分钟

这是我参与8月更文挑战的第1天,活动详情查看:8月更文挑战

1628664150.jpg

对象的创建过程

  1. class loading
  2. class linking(verification、preparation、resolution)
  3. class initializing
  4. 申请/分配 对象内存
  5. 成员变量赋默认值
  6. 调用构造方法
    • 成员变量顺序赋初始值
    • 执行构造方法语句

前三步是在类加载过程中完成

对象在内存中的存储布局

观察虚拟机配置

java -XX:+PrintCommandLineFlags -version

-XX:InitialHeapSize=132670528 -XX:MaxHeapSize=2122728448 -XX:+PrintCommandLineFlags -XX:>+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC java version "1.8.0_181" Java(TM) SE Runtime Environment (build 1.8.0_181-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)

普通对象

  1. 对象头:markword  8字节

  2. ClassPointer指针:-XX:+UseCompressedClassPointers 为4字节 不开启为8字节

  3. 实例数据    引用类型:-XX:+UseCompressedOops 为4字节 不开启为8字节

   Oops Ordinary Object Pointers(普通对象指针String等)

  1. Padding对齐,8的倍数

数组对象

  1. 对象头:markword 8
  2. ClassPointer指针同上
  3. 数组长度:4字节
  4. 数组数据
  5. 对齐 8的倍数

实验(查看对象在内存中占多少字节)

class文件load到内存的过程中能够被agent(代理)截获信息进行修改

  1. 新建项目ObjectSize (1.8)

  2. 创建文件ObjectSizeAgent

package com.mashibing.jvm.agent;

import java.lang.instrument.Instrumentation;

public class ObjectSizeAgent {
    private static Instrumentation inst;
       
    //jvm调用(固定格式)
    public static void premain(String agentArgs, Instrumentation _inst) {
        inst = _inst;
    }
       
    //自定义方法
    public static long sizeOf(Object o) {
        return inst.getObjectSize(o);
    }
}
  1. src目录下创建META-INF/MANIFEST.MF
Manifest-Version: 1.0
Created-By: mashibing.com
Premain-Class: com.mashibing.jvm.agent.ObjectSizeAgent

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

  1. 打包jar文件

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

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

-javaagent:C:\work\ijprojects\ObjectSize\out\artifacts\ObjectSize_jar\ObjectSize.jar

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()));
      }
      
      //一个Object占多少个字节
      // -XX:+UseCompressedClassPointers -XX:+UseCompressedOops
      // Oops = ordinary object pointers
      private static class P {
                          //8 _markword
                          //4 _oop指针
          int id;         //4
          String name;    //4
          int age;        //4
  
          byte b1;        //1
          byte b2;        //1
  
          Object o;       //4
          byte b3;        //1
  
      }
  }

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

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

IdentityHashCode的问题

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

cloud.tencent.com/developer/a…

cloud.tencent.com/developer/a…

cloud.tencent.com/developer/a…

cloud.tencent.com/developer/a…

对象定位

blog.csdn.net/clover_lily…

  1. 句柄池

1628674694.jpg

  1. 直接指针

1628674793.jpg

对象头具体包括什么

1628672123.jpg

markword 64位

下面的图是32位的,64位的与之类似

1628672599.jpg

  1. hashCode部分:

1628673212.jpg

问题:为什么GC年龄默认为15?(最大为15)

答:分代年龄占4bit,能表示的区间0-15

对象分配

1628675228.jpg