7. 2026金三银四 Java 虚拟机面试终极版:32 道必考题 + 图解 + 源码精讲


Q1【P0】JVM 运行时数据区域划分、线程私有/共享及各自作用

核心答案

  • 程序计数器:线程私有,记录当前字节码行号,唯一不出现 OOM。
  • 虚拟机栈 :线程私有,存放栈帧(局部变量表、操作数栈、动态链接、方法出口),深度溢出抛 StackOverflowError
  • 本地方法栈:线程私有,为 Native 方法服务。
  • :线程共享,存放所有对象实例和数组,GC 主战场,可能 OOM。
  • 方法区:线程共享,存储类元数据、常量池、静态变量、方法信息。JDK8 后由**元空间(Metaspace)**实现,使用本地内存。

🔁 Mermaid 流程图

graph TB subgraph 线程私有 PC[程序计数器] VMS[虚拟机栈] --> SF[栈帧] NMS[本地方法栈] end subgraph 线程共享 Heap[堆] --> Obj[对象实例] MA[方法区/元空间] --> Meta[类信息/常量/静态变量] end

🧩 精简源码(栈溢出示例)

java 复制代码
public class StackOverflowDemo {
    public static void recursive() { recursive(); }
    public static void main(String[] args) {
        recursive(); // 抛出 StackOverflowError
    }
}

Q2【P0】JVM 堆内存结构划分、新生代/老年代比例及对象分配策略

核心答案

  • 堆结构:新生代(1/3) + 老年代(2/3)。
  • 新生代内部分配:Eden : Survivor From : Survivor To = 8 : 1 : 1。
  • 分配流程
    1. 新对象优先在 Eden 区分配。
    2. Eden 满 → Minor GC → 存活对象移入空闲 Survivor。
    3. 对象每经历一次 Minor GC 年龄+1,默认 15 晋升老年代。
    4. 大对象(如长数组)直接进入老年代。
    5. 老年代满 → Full GC。

🔁 Mermaid 流程图

graph TB New[新对象] --> Eden[Eden区] Eden -->|满| MinorGC[Minor GC] MinorGC --> Survivor[存活对象→Survivor To] Survivor -->|年龄≥15| Old[晋升老年代] Old -->|满| FullGC[Full GC]

🧩 精简源码

java 复制代码
public class HeapAllocTest {
    public static void main(String[] args) {
        while (true) {
            byte[] temp = new byte[1024 * 1024];
        }
    }
}
// VM参数:-Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails

Q3【P0】GC 可达性分析算法原理及废弃引用计数的原因

核心答案

  • 可达性分析 :从 GC Roots 出发遍历引用链,不可达对象判定为可回收。
  • GC Roots 包含:栈引用、静态属性/常量引用、JNI 引用、活跃线程等。
  • 引用计数缺陷:无法解决循环引用(如 A→B→A,外部无引用但计数器不为 0),JVM 废弃。

🔁 Mermaid 流程图

graph TB GC[GC Roots] --> A[对象A] A --> B[对象B] B -.->|循环引用| A C[对象C] -.->|无引用链| D[可回收]

🧩 精简源码(循环引用可回收)

java 复制代码
class Node { Node next; }
public class CircleRefDemo {
    public static void main(String[] args) {
        Node a = new Node();
        Node b = new Node();
        a.next = b; b.next = a;
        a = null; b = null;
        System.gc(); // 可达性分析可正常回收
    }
}

Q4【P0】四种引用类型:强/软/弱/虚引用的区别、回收时机及应用场景

核心答案

  • 强引用:默认引用,永不回收(即使 OOM)。
  • 软引用:内存不足时回收,适用缓存(图片、大对象)。
  • 弱引用:下一次 GC 必回收,适用防止内存泄漏(如 Handler 持有 Activity)。
  • 虚引用 :无法获取对象,仅用于监控回收(配合 ReferenceQueue),适用堆外内存释放(如 DirectBuffer)。

🔁 Mermaid 流程图

graph LR Strong[强引用] -->|永不回收| Soft[软引用] -->|内存不足回收| Weak[弱引用] -->|每次GC回收| Phantom[虚引用]

🧩 精简源码

java 复制代码
import java.lang.ref.*;
public class RefDemo {
    public static void main(String[] args) {
        Object strong = new Object();
        SoftReference<Object> soft = new SoftReference<>(new Object());
        WeakReference<Object> weak = new WeakReference<>(new Object());
        ReferenceQueue<Object> queue = new ReferenceQueue<>();
        PhantomReference<Object> phantom = new PhantomReference<>(new Object(), queue);
    }
}

Q5【P0】类加载的完整生命周期(7个阶段)及每阶段工作

核心答案

  1. 加载:读取 class 二进制流,生成 Class 对象。
  2. 验证:校验字节码合法性。
  3. 准备:为静态变量分配内存并赋默认零值。
  4. 解析:将符号引用替换为直接引用。
  5. 初始化:执行静态代码块,为静态变量赋自定义值。
  6. 使用:实例化对象、调用方法。
  7. 卸载:类加载器回收后,卸载类元数据。

🔁 Mermaid 流程图

graph LR Load[加载] --> Verify[验证] --> Prepare[准备] --> Resolve[解析] --> Init[初始化] --> Use[使用] --> Unload[卸载]

🧩 精简源码(观察初始化阶段)

java 复制代码
public class ClassInitDemo {
    static { System.out.println("静态代码块执行,即初始化阶段"); }
    public static void main(String[] args) {
        // 触发初始化
    }
}

Q6【P0】双亲委派模型原理、执行流程及设计目的

核心答案

  • 原理:类加载器收到请求后,先委派给父加载器,层层向上到启动类加载器;父加载器无法加载时,才由子加载器自己加载。
  • 流程:自定义 → 应用类加载器 → 扩展类加载器 → 启动类加载器。
  • 目的:避免重复加载类、防止核心类库被篡改(沙箱安全)、保证类优先级。

🔁 Mermaid 流程图

graph TD Custom[自定义类加载器] -->|委托| App[应用类加载器] App -->|委托| Ext[扩展类加载器] Ext -->|委托| Boot[启动类加载器] Boot -->|无法加载| Ext -->|无法加载| App -->|自己加载| Custom

🧩 精简源码(自定义类加载器)

java 复制代码
public class CustomClassLoader extends ClassLoader {
    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        // 遵循双亲委派
        return super.loadClass(name);
    }
}

Q7【P0】Minor GC、Major GC、Full GC 的区别及触发时机

核心答案

  • Minor GC:只回收新生代,频繁快速,Eden 满触发。
  • Major GC:只回收老年代(较少单独出现)。
  • Full GC :回收整个堆 + 方法区/元空间,耗时最长。触发条件:老年代空间不足、手动 System.gc()、Minor GC 后晋升对象放不下、元空间满。

🔁 Mermaid 流程图

graph TD Eden满 --> MinorGC[Minor GC] Old满 --> FullGC[Full GC] System.gc() --> FullGC Metaspace满 --> FullGC

🧩 精简源码

java 复制代码
public class GcTriggerDemo {
    public static void main(String[] args) {
        System.gc(); // 建议JVM执行Full GC
    }
}

Q8【P0】JVM 三大垃圾回收算法:复制、标记-清除、标记-整理的原理与适用场景

核心答案

算法 原理 优点 缺点 适用区域
复制 存活对象复制到空闲区,清空原区 无碎片,简单 内存浪费(双倍空间) 新生代
标记-清除 标记垃圾后直接清除 快,不移动对象 产生内存碎片 老年代(CMS)
标记-整理 标记后存活对象向一端移动,清理边界 无碎片,紧凑 移动对象开销大 老年代(Serial Old)

🔁 Mermaid 流程图(以标记-整理为例)

graph LR Before[标记前:存活+垃圾] --> Mark[标记存活对象] --> Compact[向左移动存活对象] --> After[清理边界:无碎片]

🧩 精简源码

算法为 JVM 内置,无特定代码;可通过 GC 日志观察。


Q9【P0】JDK8 废弃永久代改用元空间的原因

核心答案

  • 永久代大小固定,容易 OOM(尤其动态生成类场景)。
  • 元空间使用本地物理内存,不受 JVM 堆限制,默认无上限。
  • 类元数据、常量池、方法信息移入元空间,减少 Full GC 频率。
  • 方便热部署、插件化、动态代理等场景。

🔁 Mermaid 流程图

graph LR JDK7[JDK7:永久代 堆内] -->|JDK8| JDK8[JDK8:元空间 本地内存]

🧩 精简源码

无法代码演示,属于 JVM 底层内存布局变更。


Q10【P0】Android 中常见 JVM 内存泄漏的本质与典型场景

核心答案

  • 本质:本应被回收的对象,被 GC Roots 强引用链持有,导致无法回收。
  • 典型场景
    1. 静态变量长期持有 Activity/View/Context。
    2. 匿名内部类(如 Handler、AsyncTask)隐式持有外部类。
    3. 全局集合(ArrayList、HashMap)未清空。
    4. 资源未关闭:Cursor、FileInputStream、Bitmap。
    5. 单例模式中持有 Activity 上下文而非 Application 上下文。

🔁 Mermaid 流程图

graph TD GC[GC Roots] -->|强引用| Leak[无辜对象] -->|无法回收| MemLeak[内存泄漏] --> OOM

🧩 精简源码(静态持有 Activity)

java 复制代码
public class StaticLeakDemo {
    private static Object sHold;
    public static void hold(Object obj) { sHold = obj; }
}

Q11【P0】JVM 虚拟机栈的栈帧组成

核心答案

每个栈帧包含:

  • 局部变量表:存储方法参数和局部变量(以 slot 为单位)。
  • 操作数栈:存放计算过程中的中间结果。
  • 动态链接:指向运行时常量池中该方法的符号引用。
  • 方法返回地址:正常或异常退出后的返回点。
  • 附加信息:调试信息等。

🔁 Mermaid 流程图

graph TB subgraph 虚拟机栈 Frame3[栈帧3 方法C] Frame2[栈帧2 方法B] Frame1[栈帧1 方法A] end subgraph 栈帧详细结构 LV[局部变量表] OS[操作数栈] DL[动态链接] RA[返回地址] end Frame1 --> LV & OS & DL & RA

🧩 精简源码(通过 javap 查看)

java 复制代码
public class StackFrameDemo {
    public static void methodA(int a, int b) { int c = a + b; methodB(c); }
    private static void methodB(int sum) { System.out.println(sum); }
    public static void main(String[] args) { methodA(1,2); }
}
// 命令:javap -c -v StackFrameDemo.class

Q12【P0】JVM 对象创建的完整过程(从 new 到初始化)

核心答案

  1. 检查类是否已加载、链接、初始化。
  2. 分配内存(指针碰撞或空闲列表)。
  3. 初始化对象头(MarkWord、类型指针)。
  4. 实例数据赋默认零值。
  5. 执行 <init> 构造方法,按程序赋值。

🔁 Mermaid 流程图

graph TD New[new 对象] --> Check[类加载校验] Check --> Alloc[分配堆内存] Alloc --> Header[初始化对象头] Header --> Zero[实例数据默认零值] Zero --> Init[执行构造方法]

🧩 精简源码

java 复制代码
public class ObjectCreateDemo {
    public static void main(String[] args) {
        User user = new User(); // 触发完整创建流程
    }
}
class User { int id; String name; }

Q13【P1】CMS 垃圾收集器的四步执行流程及优缺点

核心答案

  • 流程:初始标记(STW) → 并发标记 → 重新标记(STW) → 并发清除。
  • 优点:大部分阶段与用户线程并发,低停顿。
  • 缺点:标记-清除产生碎片;无法处理浮动垃圾;占用 CPU 高。

🔁 Mermaid 流程图

graph LR InitMark[初始标记 STW] --> ConMark[并发标记] --> Remark[重新标记 STW] --> ConSweep[并发清除]

🧩 精简源码(指定 CMS 参数)

bash 复制代码
-XX:+UseConcMarkSweepGC

Q14【P1】G1 垃圾收集器的核心原理与 Region 分区概念

核心答案

  • 将堆划分为多个大小相等的 Region,不分固定新生代/老年代。
  • 追踪每个 Region 的垃圾堆积价值,优先回收垃圾最多的 Region。
  • 可实现可预测停顿,兼顾吞吐量与低延迟。
  • JDK9+ 默认垃圾收集器。

🔁 Mermaid 流程图

graph TB Heap[堆内存] --> R1[Region Eden] Heap --> R2[Region Survivor] Heap --> R3[Region Old] Heap --> R4[Region Humongous] R1 & R2 & R3 & R4 --> GC[优先回收垃圾最多的Region]

🧩 精简源码

bash 复制代码
-XX:+UseG1GC

Q15【P1】JVM 对象的内存布局(对象头、实例数据、对齐填充)

核心答案

  • 对象头:MarkWord(哈希码、GC 年龄、锁状态) + 类型指针(指向方法区类元信息)。
  • 实例数据:对象中各个字段的值。
  • 对齐填充:保证对象大小是 8 字节的整数倍。

🔁 Mermaid 流程图

graph LR Header[对象头] --> Instance[实例数据] --> Padding[对齐填充] subgraph Header内容 Mark[MarkWord] Type[类型指针] end

🧩 精简源码(使用 jol 查看)

java 复制代码
// 依赖:org.openjdk.jol:jol-core
public class ObjectLayoutDemo {
    private int id;
    public static void main(String[] args) {
        ObjectLayoutDemo obj = new ObjectLayoutDemo();
        // System.out.println(ClassLayout.parseInstance(obj).toPrintable());
    }
}

Q16【P1】逃逸分析是什么?它能带来哪些优化?

核心答案

  • 逃逸分析:分析对象的作用域是否会逃逸出当前方法或线程。
  • 优化手段
    • 栈上分配:未逃逸对象直接在栈上分配,避免堆分配和 GC。
    • 标量替换:将对象字段拆分为基本类型,存储在栈上。
    • 同步消除:未逃逸对象的锁可以消除(本合集已剔除锁相关内容,仅提及)。
  • 效果:降低堆压力,提升性能。

🔁 Mermaid 流程图

graph TD Obj[创建对象] --> Escape{逃逸分析} Escape -->|未逃逸| Stack[栈上分配/标量替换] Escape -->|已逃逸| Heap[堆分配]

🧩 精简源码

java 复制代码
public class EscapeDemo {
    public void test() {
        Point p = new Point(1, 2); // 未逃逸,可栈上分配
        System.out.println(p.x);
    }
    class Point { int x,y; Point(int x,int y){this.x=x;this.y=y;} }
}
// VM参数:-XX:+DoEscapeAnalysis -XX:+PrintEscapeAnalysis

Q17【P1】Class 文件常量池、运行时常量池、字符串常量池的区别

核心答案

  • Class 常量池 :编译期生成,存在于 .class 文件中,存字面量和符号引用。
  • 运行时常量池 :类加载后移入方法区(元空间),支持动态添加(如 String.intern())。
  • 字符串常量池:JDK7+ 位于堆中,专门缓存字符串字面量,避免重复创建。

🔁 Mermaid 流程图

graph LR ClassFile[.class文件常量池] -->|类加载| Runtime[运行时常量池 方法区] StringLiteral[字符串字面量] -->|intern| StringPool[字符串常量池 堆]

🧩 精简源码

java 复制代码
public class ConstantPoolDemo {
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = new String("hello");
        System.out.println(s1 == s2.intern()); // true
    }
}

Q18【P1】Android ART 虚拟机与标准 JVM 的核心区别

核心答案

特性 JVM(HotSpot) Android ART
执行方式 解释执行 + JIT AOT 预编译(5.0-6.0);混合模式(7.0+: 解释+JIT+后台AOT)
字节码 .class.jar .dex.oat / .odex
GC 算法 分代收集(CMS/G1/ZGC) 并发复制(Concurrent Copying)+ 标记清除
启动速度 较慢 更快
内存占用 相对较低 略高(AOT 后存储空间)

🔁 Mermaid 流程图

graph LR subgraph JVM Dex1[.dex] --> Interpret[解释执行] --> JIT[JIT编译] end subgraph ART Dex2[.dex] --> AOT[安装期AOT编译] --> Native[本地机器码运行] end

🧩 精简源码(Android 中观察 ART GC)

java 复制代码
System.gc(); // logcat 过滤 "art" 查看 GC 信息

Q19【P1】JVM 类初始化的触发时机及不触发的情况

核心答案

  • 触发new 实例、调用静态方法、访问静态非常量字段、反射 Class.forName()、子类初始化触发父类。
  • 不触发 :仅声明引用(如 Person p = null;)、访问静态常量(编译期常量)、通过数组引用类。

🔁 Mermaid 流程图

graph TD Trigger[触发初始化] --> New[new实例] Trigger --> StaticMethod[调用静态方法] Trigger --> StaticField[访问静态非常量字段] Trigger --> Reflect[反射 Class.forName] Trigger --> SubClass[子类初始化] NoTrigger[不触发初始化] --> Declare[仅声明变量] NoTrigger --> Constant[访问静态常量] NoTrigger --> ArrayRef[数组引用]

🧩 精简源码

java 复制代码
public class InitTriggerDemo {
    public static void main(String[] args) {
        Person p = null;      // 不会触发初始化
        System.out.println(Person.CONST); // 若CONST是编译期常量,也不触发
    }
}
class Person {
    static { System.out.println("初始化"); }
    static final int CONST = 100;
}

Q20【P1】JVM 类卸载需要满足的条件

核心答案

  1. 该类的所有实例已被回收。
  2. 加载该类的 Class 对象没有任何引用。
  3. 加载该类的类加载器已被回收。

三个条件同时满足时,类元数据才会被卸载。

🔁 Mermaid 流程图

graph LR AllInst[所有实例已回收] --> ClassRef[Class无引用] --> Loader[类加载器已回收] --> Unload[类卸载]

🧩 精简源码(通常需结合自定义 ClassLoader 演示)

java 复制代码
// 示例难以直接展示,需配合自定义类加载器并清空引用后调用 GC

Q21【P1】Stop-The-World(STW)的概念、触发事件及减少方法

核心答案

  • STW:GC 时暂停所有应用线程。
  • 触发 STW 的 GC 事件:Minor GC、Full GC、CMS 初始标记和重新标记、G1 初始标记和最终标记。
  • 减少方法:使用并发收集器(CMS/G1)、调整新生代大小、减少 Full GC 频率(避免大对象、合理设置元空间)。

🔁 Mermaid 流程图

graph LR App[应用线程运行] --> GC[触发GC] --> STW[全部暂停 STW] --> Execute[执行GC] --> Resume[恢复所有线程]

🧩 精简源码(通过 JVM 参数观察)

bash 复制代码
-XX:+PrintGCApplicationStoppedTime -XX:+PrintSafepointStatistics

Q22【P1】SafePoint(安全点)和 SafeRegion(安全区域)的作用

核心答案

  • SafePoint:程序执行中的特定位置(如循环末尾、方法返回前),线程在此处暂停以执行 GC 等 VM 操作。
  • SafeRegion:一段引用关系不会变化的代码区域(如线程处于 Sleep/Blocked 状态),GC 可安全忽略该线程。
  • 作用:保证 GC 时所有线程能快速到达一致状态,避免扫描不稳定的栈。

🔁 Mermaid 流程图

graph TD Code[代码执行] --> Check{是否达到SafePoint?} Check -->|是| Pause[暂停线程] --> GC --> Resume[恢复] Check -->|否| Continue[继续执行]

🧩 精简源码(通过 JVM 参数打印安全点停顿)

bash 复制代码
-XX:+PrintGCApplicationStoppedTime -XX:+PrintSafepointStatistics

Q23【P1】JVM 参数 -Xms/-Xmx/-Xmn/-XX:MetaspaceSize 含义及 Android 堆设置

核心答案

  • -Xms:堆初始大小。
  • -Xmx:堆最大大小。
  • -Xmn:新生代大小(老年代 = 堆 - 新生代)。
  • -XX:MetaspaceSize:元空间触发 Full GC 的阈值。
  • Android 设置 :在 AndroidManifest.xml 中声明 android:largeHeap="true" 请求更大堆(具体值因设备而异)。

🔁 Mermaid 流程图

graph TD Heap[堆] --> Young[新生代 -Xmn] --> Eden[Eden] Young --> S0[Survivor0] Young --> S1[Survivor1] Heap --> Old[老年代] Meta[元空间] -->|本地内存| NativeMemory

🧩 精简源码(Android 大堆)

xml 复制代码
<application android:largeHeap="true">

Q24【P1】GC Roots 包含哪些?请列举至少 4 种

核心答案

  1. 虚拟机栈(局部变量表)中引用的对象。
  2. 方法区中静态属性引用的对象。
  3. 方法区中常量引用的对象。
  4. JNI(Native 方法)引用的对象。
  5. 活跃线程(Thread 对象)。
  6. 同步监视器(synchronized 锁对象,本合集已剔除但可作为扩展)。

🔁 Mermaid 流程图

graph TD GC[GC Roots] --> Stack[栈引用] GC --> Static[静态属性引用] GC --> Constant[常量引用] GC --> JNI[JNI引用] GC --> Thread[活跃线程]

🧩 精简源码(验证 GC Roots)

java 复制代码
public class GCRootsDemo {
    private static Object staticObj = new Object();   // 静态引用
    private static final Object constObj = new Object(); // 常量引用
    public void method() {
        Object localObj = new Object();   // 栈引用
        System.gc(); // 这三者均不会被回收
    }
}

Q25【P2】JVM 内存溢出(OOM)的常见触发场景

核心答案

  • 堆 OOM:不断创建大对象、集合无限添加、大量 Bitmap。
  • 元空间 OOM:动态生成大量类(如热修复、插件化、动态代理)。
  • 栈 OOM:递归过深或线程数量过多(线程过多导致栈内存不足)。
  • 堆外内存 OOM:Native ByteBuffer、未释放的 Bitmap 像素内存。

🔁 Mermaid 流程图

graph TD HeapOOM[堆OOM] --> BigObj[大对象/集合无限] MetaOOM[元空间OOM] --> DynamicClass[动态生成大量类] StackOOM[栈OOM] --> DeepRecursion[递归深度过大] NativeOOM[堆外OOM] --> BitmapUnreleased[Bitmap未释放]

🧩 精简源码(堆 OOM 示例)

java 复制代码
import java.util.ArrayList;
public class HeapOOM {
    public static void main(String[] args) {
        ArrayList<byte[]> list = new ArrayList<>();
        while (true) {
            list.add(new byte[1024 * 1024]); // 不断分配1MB数组
        }
    }
}
// VM参数:-Xms10M -Xmx10M

Q26【P2】符号引用与直接引用的区别?解析阶段做了什么?

核心答案

  • 符号引用:编译期字符串形式描述类、方法、字段,无实际内存地址。
  • 直接引用:运行时真实内存指针、偏移地址。
  • 解析阶段:将符号引用替换为直接引用,绑定真实内存地址。

🔁 Mermaid 流程图

graph LR Symbol[符号引用 字符串] --> Resolve[解析阶段] --> Direct[直接引用 内存地址/偏移]

🧩 精简源码(概念性)

java 复制代码
// Java 代码中的方法调用在 class 文件中存为符号引用,运行时转换为直接引用

Q27【P2】JVM 内存分配方式:指针碰撞与空闲列表的区别

核心答案

  • 指针碰撞:堆内存规整时,用指针标记分配位置,分配时向后移动指针。效率高。
  • 空闲列表:堆内存有碎片时,维护空闲内存列表,分配时遍历找到合适空间。

🔁 Mermaid 流程图

graph TD Compact[内存规整] --> Pointer[指针碰撞 简单移动指针] Fragmented[内存碎片] --> FreeList[空闲列表 遍历查找]

Q28【P2】字符串 intern() 方法的底层常量池复用逻辑

核心答案

  • intern():将字符串放入字符串常量池,如果池中已存在则返回池中引用,否则存入并返回。
  • 作用:复用字符串对象,节省内存,减少重复创建。

🔁 Mermaid 流程图

graph TD Intern[调用 intern] --> Check{常量池中是否存在?} Check -->|存在| Return[返回池中引用] Check -->|不存在| Add[加入常量池] --> Return2[返回新引用]

🧩 精简源码

java 复制代码
public class InternDemo {
    public static void main(String[] args) {
        String s1 = new String("abc").intern();
        String s2 = "abc";
        System.out.println(s1 == s2); // true
    }
}

Q29【P2】Android 中 Bitmap 内存占用与 JVM 堆外内存的关系

核心答案

  • 高版本 Android(8.0+)中,Bitmap 的像素数据存放在堆外 Native 内存,不在 JVM 堆内。
  • JVM 堆中只保留 Bitmap 对象头引用。
  • 堆外内存需要主动调用 recycle() 释放,否则会导致 Native 内存泄漏,同样引发 OOM。

🔁 Mermaid 流程图

graph LR subgraph JVM堆 BitmapObj[Bitmap对象 引用] end subgraph Native堆 PixelData[像素数据] end BitmapObj --> PixelData

🧩 精简源码(模拟 Bitmap 使用)

java 复制代码
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.large);
// 使用完毕后需及时释放
bitmap.recycle();

Q30【P2】JVM 方法区(元空间)中具体存放哪些内容?

核心答案

  • 类版本信息、字段信息、方法信息。
  • 运行时常量池。
  • 静态变量(JDK7 后移到堆,但逻辑上属于方法区)。
  • 即时编译器(JIT)编译后的代码缓存。
  • 注解元数据。

🔁 Mermaid 流程图

graph TB Meta[方法区/元空间] --> ClassInfo[类结构信息 版本/字段/方法] Meta --> RuntimePool[运行时常量池] Meta --> Static[静态变量 逻辑上] Meta --> JITCode[JIT编译代码缓存] Meta --> Annotation[注解元数据]

Q31【P2】新生代为什么不用标记-清除或标记-整理算法?

核心答案

  • 新生代对象存活率极低(约 98% 以上一次性回收),复制算法成本最低(只需复制少量存活对象)。
  • 标记-清除会产生碎片,新生代频繁分配回收会导致碎片严重。
  • 标记-整理需要移动大量存活对象,开销远大于复制算法。

🔁 Mermaid 流程图

graph LR Young[新生代 存活率低] --> Copy[复制算法 最优] Old[老年代 存活率高] --> MarkCompact[标记-整理 更合适]

Q32【P2】JVM 启动类加载器、扩展类加载器、应用类加载器的职责

核心答案

  • 启动类加载器(Bootstrap) :加载 JDK 核心类库(rt.jar 等),C++ 实现,无父加载器。
  • 扩展类加载器(Extension) :加载 jre/lib/ext 下的扩展 jar 包。
  • 应用类加载器(Application) :加载 CLASSPATH 下的项目类和第三方依赖。

🔁 Mermaid 流程图

graph TD Boot[启动类加载器] -->|父| Extension[扩展类加载器] Extension -->|父| App[应用类加载器] App -->|父| Custom[自定义类加载器]

🧩 精简源码(打印类加载器层级)

java 复制代码
public class ClassLoaderHierarchy {
    public static void main(String[] args) {
        ClassLoader cl = ClassLoaderHierarchy.class.getClassLoader();
        while (cl != null) {
            System.out.println(cl);
            cl = cl.getParent();
        }
    }
}

相关推荐
止语Lab42 分钟前
好的 DX 不等于少写代码——三种语言的摩擦力设计课
后端
吃饱了得干活42 分钟前
别再手动解析 LLM 输出了!LangChain 四种结构化输出方案对比
后端·python·langchain
程序员天天困1 小时前
Arthas trace 命令怎么用?一行定位最慢那行代码
jvm·后端
Huiturn1 小时前
GPT 5.6 连续编码 10 小时,纯 Python 啃下 Word 二进制格式——doc2docx 实现拆解
后端
用户298698530141 小时前
Python 实现 Excel 与 Markdown 互转的实用指南
后端·python·excel
用户77283104908401 小时前
krono-job:零侵入、单二进制交付的分布式任务调度平台(开源)
后端
Conan在掘金1 小时前
鸿蒙报错速查:Function lacks ending return statement,返回路径漏 return 就炸,根因 + 真解法
后端
人间凡尔赛1 小时前
AI-Native 云原生架构:2026 年从容器编排到智能体编排的范式革命
后端·云原生·架构
IT_陈寒2 小时前
Vue的响应式让我加班到凌晨3点,原来问题出在这
前端·人工智能·后端
卷无止境2 小时前
提升 Python 代码健壮性的方法大盘点
后端·python