在前边 话说 类加载过程的文章中已经介绍过了类加载过程
创建对象的时候会先去判断类是否已经加载,
如果没有加载的话会先加载类,
如果已经加载就会直接创建对象。
步骤如下:
1.class loading
2.class linking (vertification prepration resolution)
3.class initiaizing
4.申请对象内存
5.成员变量赋默认值
6.调用构造方法
6.1 成员变量赋初始值
6. 2 执行构造方法语句 (super先行)
java -XX:+PrintCommandLineFlags -version

-XX:+UseCompressedClassPointer 开启Class Pointer指针大小是否压缩, 默认是8字节 开启压缩之后变为4字节
-XX:+UseCompressedOops 这个是指引用类型指针大小是否压缩,这个默认也是8字节 开启压缩之后变为4字节
  1. 对象头  markword  8字节 
  2. classPointer 压缩后4字节  不压缩8字节 
     classpointer指向class对象 new T() 的话  classpointer就是指向T.class 这个对象
  3. 实例数据
     byte:1字节 
     short:2 字节
     char:2字节
     int:4字节
     float:4字节
     double:8字节 
     long:8字节
      如果是引用类型压缩后4字节 不压缩8字节 
  4. padding 对齐  ,对象大小总是为8的倍数个字节 如果不够就对齐

1. 对象头 markword 2.classPointer 指针 指向数组元素类型的类 比入 new int[10] 就是指向int.class 3. 数组长度 : 4字节 最长int的最大值了呗 4. 数组数据 5. padding 对齐

agent 字节码文件在加载到内存的时候可以用一个agent截取到二进制的字节码,然后可以对字节码进行修改,也可以获取大小
定义class
package vip.freeedu;
     import java.lang.instrument.Instrumentation;
     public class MyAgent {
         // 定义一个静态变量 存起来Instrumentation
         private static Instrumentation instrumentation;
         public static void premain(String agentArgs,Instrumentation _instrumentation){
             instrumentation = _instrumentation;
         }
         // 调用getObjectSize方法获取对象大小
         public static long sizeOf(Object o){
             return instrumentation.getObjectSize(o);
         }
     }
添加META-INF/MANIFEST.MF 这一行一定要回车换行 保证idea没有报红
Manifest-Version: 1.0 Premain-Class: vip.freeedu.MyAgent
打成jar包








新建一个项目 把jar包加进去 不知道怎么加 ? 上图


编写测试类
public class TestSize {
         public static void main(String[] args) {
             Object o = new Object();
             int[] arr = new int[1];
             T t = new T();
             System.out.println("object长度:"+MyAgent.sizeOf(o));
             System.out.println("int[]长度:"+MyAgent.sizeOf(arr));
             System.out.println("t的长度:"+MyAgent.sizeOf(t));
        }
     }
     class T{
         int id;
         int age;
         String name ;
         byte b01;
         float f ;
         long l;
     }




看结果:
        object长度:16 
                 // markword(8) + 压缩的classpointer(4) + 成员属性(0)+ 对齐(4)
        int[]长度:16
                  // markword(8) + 压缩的classpointer(4) + 数组长度(4) +数组数据(0)+ 对齐(0)
        t的长度:40
                 // markword(8) + 压缩的classpointer(4) + id(4) 
                 // + age(4) + name(4) + b01(1) + f(4) + l(8) + 对齐(3)
三、对象头具体包括什么
这个很复杂 这里简单介绍(以32位为例):
主要记住锁+垃圾回收分代年龄
无锁:001
偏向锁:101
轻量级锁:00
重量级锁:10
GC标记:11
分代年龄:4bit 最大为15 这就是GC年龄为默认为15

四、对象怎么定位
深入理解java虚拟机中有一张图:

第一种:变量指向一个句柄 这个句柄指向堆对象+对象数据类型(方法区) :GC算法可能比较快 第二种(hotspot实现):变量指向堆对象 堆对象指向对象数据类型(方法区) :这种找对象比较快
五、对象怎么分配 分配在哪儿
这个后期垃圾回收的时候再写一篇 这里就不长篇大论了
六、Object o = new Object() 在内存占用多少字节
如果开启classpointer压缩 :
? 对象头 8字节 + classpointer 4字节 + 属性大小 0字节 + padding 4字节 = 16字节
如果未开启classPointer压缩
对象头 8字节 + classpointer 8字节 + 属性大小 0字节 + padding 0字节 = 16字节
答: 16字节
?
?
原文:https://blog.51cto.com/u_12198094/2983515