金三银四 - JVM 面试题不来看看?

122 阅读4分钟

JVM 的组成部分和作用

  • 类加载系统:根据给定的全限定名加载object
  • 执行引擎:执行class中的指令
  • 本地方法栈:nativa方法
  • 方法区:运行时数据区域
  • 作用:首先通过编译器将java代码转换成字节码,然后类加载器将字节码加载到方法区,然后将指令交给执行引擎执行,执行引擎将字节码翻译成底层计算机指令(此时需要本地方法),再由CPU执行

JVM 内存模型

  • 线程私有的
    • 本地方法栈:native 方法
    • 线程栈
      • 栈帧:每个方法分配的内存空间
        • 方法出口:方法结束时,执行哪个代码
        • 局部变量表:局部变量
        • 操作数栈:局部变量操作的数据
        • 动态链接:引用类型指向内存区域的指针
    • 程序计数器:上下文切换时,记录程序运行到哪儿
  • 线程共有的
    • 元空间:类信息,常类,静态变量
    • 堆:对象

Java 对象的创建过程

  • 类加载检查:检查类是否加载到内存中,如果没有,进行类加载
  • 分配内存空间
  • 内存赋0值:内存空间全部设置为 0(除了对象头)
  • 设置对象头:设置对象属性
  • 初始化:调用初始化方法

类加载的过程

  • 加载:根据全限定名加载class文件到内存中
  • 连接
    • 验证
    • 准备
      • 分配内存空间
      • 变量赋初值
    • 解析:常量池的符号引用解析成直接引用
  • 初始化

如何判断对象是否死亡

  • 引用计数法:每次对象被引用就+1,引用失效-1,引用为0,则死亡;
    • 优点:简单,效率高
    • 缺点:无法解决循环引用问题
  • 可达性分析:由对象出发,根据引用追溯,不能追溯到jvm定义的 GC root 对象,则视为死亡;

GC root对象有哪些(java中不能变的)

  • 栈帧中局部变量
  • 元空间的静态变量、常量
  • native对象
  • 同步锁持有的对象

GC 垃圾收集有哪些算法,都有什么特点

  • 标记-清除:将垃圾标记,然后等到安全点直接删除
    • 缺点:会出现碎片化内存
  • 标记-复制:将内存区域分为两块,每次使用一块区域,标记垃圾,等到安全点将非垃圾对象复制到另一块区域,格式化原区域
    • 总有一半内存不使用
  • 标记-整理:同标记清除类似,只不过将非垃圾对象向一端移动,清除其他区域
    • 相对于上面两种,效率比较低
  • 分代收集算法:将java堆分为新生代-老年代,在新生代对象朝生夕死,所以采用标记-复制,老年代对象相对稳定,所以采用标记-清除/标记-整理

什么是空间担保分配机制

是一种减少full GC的策略,在发生minor GC时,会检查老年代的内存空间是否大于当前新生代的总和。如果大于直接进行minor GC;如果小于,就会检查是否设置了空间担保,如果担保就会检查老年代内存空间是否大于历届minor GC 剩余的对象,如果大于,则尝试一次minor GC,否则直接 FULL GC

JVM内存溢出排查 OOM

  1. 通过 jps 查看服务 PID
  2. jmap -heap PID 查看内存情况
  3. jmap -dump:format=b,file=/tmp/heap.hprof PID 导出 dump 文件
  4. 然后可以通过本地分析工具进行分析(idea 插件 JProfiler)

怎么查看GC状态

  1. 通过 jps 查看服务 PID
  2. jstat -gc PID 事件间隔 打印次数

new Obect()占多少字节?

16字节!
一个对象包含三块区域:对象头(mark word、对象指针、数组长度)、实例数据、对齐填充;

  • 对象头:
    • mark word:8字节;
    • 对象指针:4字节;
    • 数组长度:单纯的对象不是数组,没有这块;
  • 实例数据:new object() 没有实例数据,为空;
  • 对齐填充:对象大小要求是 8 的整数倍,所以 还需要填充 4 字节