JVM八股

一、内存模型

方法区包含什么

方法区存储于使用本地内存的元空间中

  • 类的元信息:类的结构信息、字段信息、方法信息
  • 常量池:字面量、符号引用、运行时常量池(存储类加载的解析阶段符号引用解析成的直接引用)
  • 静态变量:

方法区中的方法的执行过程

  1. 类加载检查
  2. 创建栈帧,调用方法并处理返回值

为什么String是不可变的

  1. 字符串常量池的需要:创建一个String对象时,若该字符串已存在于常量池,则会直接引用已存在对象,减少JVM开销
  2. 数据安全:不可变对象是天生线程安全的,在多线程共享时不需要同步处理;同时,若字符串是可变的,可能会导致其他依赖该字符串的地方出现错误
  3. 缓存哈希:String的hashcode会将哈希值缓存于hash字段,当其作为HashMap的key时效率极高

String s = new String(“abc”)执行过程中分别对应哪些内存区域?

1. 字符串"abc"

构造方法传递一个字符串"abc",JVM会尝试拿字面量"abc"去字符串常量池获取对应String对象的引用。若没有对应引用则在堆中创建一个"abc"的String对象并将其引用保存到字符串常量池中。

2. new创建对象

new关键字将创建一个类的实例对象,创建的字符串对象在堆内存上

引用类型有哪些,有什么区别

  • 强引用:永远不会被GC回收
Object obj = new Object(); 
  • 软引用:在发生内存溢出前会进行回收;单内存足够时垃圾回收器不会回收
SoftReference<Object> softRef = new SoftReference<>(obj);
  • 弱引用:下次垃圾回收时一定会被回收,不论内存是否充足
WeakReference<Object> weakRef = new WeakReference<>(obj); 
  • 虚引用:虚引用不能直接访问对象,它们只能通过 ReferenceQueue 接收对象被回收的通知。主要用于资源清理
Object obj = new Object(); // 创建对象
ReferenceQueue<Object> queue = new ReferenceQueue<>(); // 创建引用队列
PhantomReference<Object> phantomRef = new PhantomReference<>(obj, queue);

弱引用的应用场景

  1. 对象池:用于管理暂时不使用的对象。当对象不再被强引用时,它们可以被垃圾回收,释放内存
  2. 避免内存泄漏:当一个对象不应该被长期引用时,使用弱引用可以防止该对象被意外保留,从而避免潜在的内存泄漏风险

什么情况下会发生内存溢出

  • 堆内存溢出:OutOfMemoryError:Java heap space异常,原因可能是存在大对象分配、存在太多未关闭的资源或发生内存泄漏
  • 栈溢出:StackOuverFlowError异常
  • 元空间溢出:OutOfMemoryError:Metaspace,原因可能是引用太多第三方包

什么是内存泄漏

  • 内存泄漏指占用的内存无法被正确释放,导致资源的浪费

谈谈ThreadLocal导致的内存泄漏

  • 堆中的ThreadLocalMap用于存放线程局部变量的键值对,其key是ThreadLocal的弱引用
  • 当线程消亡时,其对应的ThreadLocal不再被强引用,会被垃圾回收器回收,但其value仍然存在于ThreadLocalMap中,Entry对象仍然强引用着Value
  • 因此,建议使用ThreadLocal之后清理ThreadLocalMap(threadLocal.remove();)

内存泄漏的例子

  1. 静态属性导致内存泄漏:静态属性的生命周期通常伴随应用的整个生命周期
  2. ThreadLocal

二、类初始化和类加载

类加载检查

  1. 加载:通过类加载器读取类的字节码文件,并将其转换为一个 java.lang.Class对象
  2. 验证:确保字节码文件的格式正确,符合JVM的规范
  3. 准备:为类的静态变量分配内存,并设置默认初始值
  4. 解析:将类、接口、字段和方法的符号引用(用符号描述引用对象,间接定位目标)转换为直接引用(能够定位到目标对象)
  5. 初始化:执行类构造器<clinit>方法,完成静态变量的初始化

双亲委派模型

  • 类加载器尝试加载类时,会先将请求委派给父加载器,只有当父加载器无法加载该类时,才会尝试自己加载
  • 该机制避免类的重复加载

对象创建过程

  1. 类加载检查
  2. 分配内存
  3. 初始化对象:零初始化(将对象实例变量初始化为默认值)和字段初始化(执行类构造器/方法初始化对象的实例变量)
  4. 设置对象头
  5. 返回对象引用

三、垃圾回收

什么是Java垃圾回收机制

  • 垃圾回收是一个自动管理内存的机制,负责自动释放不再被持续应用的对象所占的内存
  • JVM有一个垃圾回收线程,它是低优先级的,只有虚拟机空闲或堆内存不足时才会执行

如何判断对象是否可以被回收

  1. 引用计数器法:为每个对象创建一个引用计数,计数为0时就可被回收。但无法解决循环引用问题
  2. 可达性分析法:从GC Root(垃圾收集根)开始遍历,追溯它们所引用的对象,不可达的判断为可回收

垃圾回收算法有哪些

  1. 标记-清除算法
    先标记可访问对象,然后遍历堆回收未标记对象
    应用场景:一般用于老年代,因为老年代对象生命周期较长
    缺点:会造成内存碎片
  2. 标记-压缩算法
    标记可访问对象后,让所有存活对象向一端移动,然后清除边界外的内存
    优缺点:解决了内存碎片问题,但移动了可用对象需要更新引用
  3. 复制算法
    将存活对象复制到一个新的对象空间中,然后清除原对象空间
    一般用于新生代,Eden区与From Survivor区/To Survivor区 复制到 To Survivor区/From Survivor区

垃圾回收器有哪些

  • Serial收集器(复制算法): 新生代单线程收集器,简单高效
  • ParNew收集器 (复制算法): 新生代收并行集器,Serial收集器的多线程版本
  • CMS(Concurrent Mark Sweep)收集器(标记-清除算法):老年代并行收集器,以获取最短回收停顿时间为目标的收集器,具有高并发、低停顿的特点,追求最短GC回收停顿时间。
  • G1(Garbage First)收集器 (标记-整理算法): Java堆并行收集器,G1收集器是JDK1.7提供的一个新收集器,G1收集器基于“标记-整理”算法实现,也就是说不会产生内存碎片。此外,G1收集器不同于之前的收集器的一个重要特点是:G1回收的范围是整个Java堆(包括新生代,老年代),而其他收集器回收的范围仅限于新生代或老年代

CMS和G1的区别

  1. 使用范围不同
    CMS收集器是老年代的收集器,可配合新生代的Serial和ParNew收集器一起使用
    G1收集器的收集范围是新生代和老年代,不需要配合其他收集器使用
  2. 垃圾回收算法
    CMS使用标记-清除算法,力求最小的停顿时间,但容易产生内存碎片
    G1使用标记-整理算法,没有内存碎片
  3. 应用场景
    CMS适用于有低延迟需求的场景
    G1适用于需要管理大堆内存、对内存碎片敏感的场景

讲讲新生代和老生代

  1. 新生代和老生代
    新生代:每次垃圾回收有大批对象死去,使用复制算法
    老年代:对象存活率高,使用标记-清除算法
  2. 年龄增长的工作机制
    虚拟机给每个对象定义了一个对象年龄计数器。如果对象在 Eden 出生并经过第一次 Minor GC 后仍然存活,并且能被 Survivor 容纳的话,将被移动到 Survivor 空间中,并将对象年龄设为 1。对象在 Survivor 区中每熬过一次 Minor GC,年龄就增加 1 岁,当它的年龄增加到一定程度(默认为 15 岁)时,就会被晋升到老年代中。

Minor GC、Major GC、Full GC的区别

Minor GC(Young GC)

  • 作用范围:只对新生代进行回收,包括Eden区和Survivor区
  • 触发条件:Eden区空间不足时
  • 特点:发生频繁,回收效率高,STW时间短

Major GC

  • 作用范围:主要针对老生代进行回收
  • 触发条件:老年代空间不足,但新生代空间足够

Full GC

  • 作用范围:整个堆内存(包括新生代、老生代、元空间)
  • 触发条件:新生代和老生代都需要被回收时、老生代空间不足且新生代无法晋升对象时
  • 特点:Full GC需要停止所有工作线程(Stop The World),遍历堆内存来查找和回收不再使用的对象,因此应尽量减少Full GC的触发

GC只会对堆进行GC吗

  • 当发生Full GC时,会对堆和方法区进行回收
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值