写点什么

话说 面试题连环问

发布于: 2021 年 04 月 05 日
话说 面试题连环问

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

在前边 “话说 类加载过程”的文章中已经介绍过了类加载过程

创建对象的时候会先去判断类是否已经加载, 如果没有加载的话会先加载类, 如果已经加载就会直接创建对象。 步骤如下:

1.class loading

2.class linking (vertification prepration resolution)

3.class initiaizing

4.申请对象内存

5.成员变量赋默认值

6.调用构造方法<init>

6. 1. 成员变量赋初始值

6.2. 执行构造方法语句 (super 先行)


二、 对象在内存中的布局

1. 查看虚拟机设置

java -XX:+PrintCommandLineFlags  -version
复制代码



-XX:+UseCompressedClassPointer 开启 Class Pointer 指针大小是否压缩, 默认是 8 字节 开启压缩之后变为 4 字节

-XX:+UseCompressedOops 这个是指引用类型指针大小是否压缩,这个默认也是 8 字节 开启压缩之后变为 4 字节


2. 普通对象

  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的倍数个字节 如果不够就对齐
复制代码

3. 数组对象

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



4. 有趣的实验 看对象大小

  1. agent 字节码文件在加载到内存的时候可以用一个 agent 截取到二进制的字节码,然后可以对字节码进行修改,也可以获取大小


  1. 定义 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);         }     }
复制代码


  1. 添加 META-INF/MANIFEST.MF 这一行一定要回车换行 保证 idea 没有报红

Manifest-Version: 1.0   Premain-Class: vip.freeedu.MyAgent  
复制代码
  1. 打成 jar 包










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




  1. 编写测试类

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;     }
复制代码


  1. 运行时要指定 javaagent





看结果:

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 位为例):

主要记住锁+垃圾回收分代年龄

  1. 无锁:001

    偏向锁:101

    轻量级锁:00

    重量级锁:10

    GC 标记:11

    分代年龄:4bit 最大为 15 这就是 GC 年龄为默认为 15


四、对象怎么定位

  1. 深入理解 java 虚拟机中有一张图:


第一种:变量指向一个句柄 这个句柄指向堆对象+对象数据类型(方法区)

GC 算法可能比较快

第二种(hotspot 实现):变量指向堆对象 堆对象指向对象数据类型(方法区)

这种找对象比较快

五、对象怎么分配

这个后期垃圾回收的时候再写一篇 这里就不长篇大论了

六、Object o = new Object() 在内存占用多少字节

如果开启 classpointer 压缩 :

对象头 8 字节 + classpointer 4 字节 + 属性大小 0 字节 + padding 4 字节 = 16 字节

如果未开启 classPointer 压缩

对象头 8 字节 + classpointer 8 字节 + 属性大小 0 字节 + padding 0 字节 = 16 字节

答: 16 字节


更多精彩欢迎关注公众号:


用户头像

还未添加个人签名 2018.03.28 加入

还未添加个人简介

评论

发布
暂无评论
话说 面试题连环问