关于java:话说-面试题连环问

42次阅读

共计 2329 个字符,预计需要花费 6 分钟才能阅读完成。

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

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

创建对象的时候会先去判断类是否曾经加载,
如果没有加载的话会先加载类,
如果曾经加载就会间接创建对象。
步骤如下:
1.class loading
2.class linking (vertification prepration resolution)
3.class initiaizing
4. 申请对象内存
5. 成员变量赋默认值
6. 调用构造方法 <init>

  1. 成员变量赋初始值
  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 截取到二进制的字节码,而后能够对字节码进行批改,也能够获取大小

    ![image](/img/bVcQ2Ch)
    
  2. 定义 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);
             }
         }
  3. 增加 META-INF/MANIFEST.MF 这一行肯定要回车换行 保障 idea 没有报红

      Manifest-Version: 1.0
      Premain-Class: vip.freeedu.MyAgent  
  4. 打成 jar 包








  5. 新建一个我的项目 把 jar 包加进去 不晓得怎么加?上图



  6. 编写测试类

    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;
         }
  7. 运行时要指定 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 位为例):

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

无锁: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 字节

有问题能够留言哦,也能够公众号留言(回复快):

正文完
 0