
以下是针对你整理的 Java 面试复习路线的详细补充按原大纲结构逐一展开。由于内容量较大本篇先完成第一部分Java 基础/JVM/JUC的完整补充。一、Java 基础与并发编程核心能力 20%1.1 JVM 内存模型JVM 在执行 Java 程序时将其管理的内存划分为5 个核心运行时数据区1.1.1 线程私有区域1程序计数器Program Counter Register记录当前线程正在执行的字节码指令地址行号字节码解释器通过改变计数器值来选取下一条要执行的指令是实现线程上下文切换的关键——线程切换后能恢复到正确的执行位置唯一不会抛出 OOM 异常的内存区域2Java 虚拟机栈Java Virtual Machine Stack为 Java 方法执行提供内存空间每个方法执行时创建一个栈帧Stack Frame栈帧包含局部变量表、操作数栈、动态链接、方法返回地址可通过-Xss参数设置栈大小如-Xss1mOOM 场景StackOverflowError线程请求栈深度超过允许最大深度如无限递归OutOfMemoryError: unable to create native thread无法为新线程分配栈内存3本地方法栈Native Method Stack为 Native 方法执行提供服务作用与虚拟机栈类似1.1.2 线程共享区域4堆内存Heap—— 垃圾回收的主要区域采用分代模型基于弱分代假说绝大多数对象朝生夕灭90% 对象存活时间极短熬过越多次 GC 的对象越难被回收区域占比核心职责Eden 区80%新对象主要分配区域Survivor 0 区10%存活对象中转站Survivor 1 区10%存活对象中转站老年代堆的 2/3存储生命周期长的对象关键参数-XX:NewRatio年轻代:老年代比例默认 1:2-XX:SurvivorRatioEden:Survivor 比例默认 8:1:15元空间Metaspace—— JDK 8 替代永久代直接使用本地内存Native Memory而非 JVM 堆内存永久代被移除的原因字符串常量池内存泄漏、方法区大小难以调优、HotSpot 与 JRockit 合并1.1.3 堆内存工作机制Young GCMinor GC执行流程新对象优先分配到 Eden 区Eden 区满时触发 Minor GC标记 Eden 区和当前 From Survivor 区的存活对象将存活对象复制到 To Survivor 区清空 Eden 区和 From Survivor 区交换 From 和 To Survivor 的角色始终有一个 Survivor 区是空的对象晋升老年代的 4 种途径正常晋升年龄达到MaxTenuringThreshold默认 15动态年龄判定Survivor 区中同龄对象总大小 Survivor 一半时提前晋升大对象直接进入超过PretenureSizeThreshold设置值空间分配担保失败Minor GC 后 Survivor 区无法容纳所有存活对象为什么 Young GC 很快绝大多数对象在 Eden 区创建后快速死亡仅扫描 Eden 和单个 Survivor不扫描老年代复制算法仅处理少量存活对象效率高1.1.4 常见 OOM 原因OOM 类型原因排查方向堆 OOM对象过多/内存泄漏jmap dump MAT 分析元空间 OOM类加载过多动态代理、热部署检查类加载器泄漏栈 OOM线程过多检查线程池使用直接内存 OOMNIO 使用不当检查 ByteBuffer 分配1.1.5 Full GC 触发条件老年代空间不足元空间空间不足调用System.gc()建议但非强制晋升失败Minor GC 后存活对象无法放入老年代大对象直接进入老年代导致空间不足1.1.6 CMS Concurrent Mode Failure原因老年代在 CMS 并发清理阶段被填满无法等到下一次 GC本质并发收集速度跟不上对象晋升速度解决方案调大老年代大小或调小年轻代提高 CMS 触发阈值-XX:CMSInitiatingOccupancyFraction使用 G1 替代 CMS1.1.7 G1 为什么能减少 STWRegion 化内存布局将堆划分为多个大小相等的 Region不再有固定的年轻代/老年代物理边界并发标记 增量回收通过并发标记阶段和增量回收避免全堆扫描可预测的停顿时间模型用户可设定目标停顿时间G1 根据历史数据智能选择回收 Region混合 GC同时回收年轻代和部分老年代 Region均衡回收效率1.1.8 ZGC 为什么可以做到几毫秒染色指针Colored Pointers在指针中编码 GC 元数据无需额外的标记位读屏障Load Barrier在对象访问时进行 GC 操作实现并发移动并发整理所有阶段标记、整理、重定位几乎都并发执行Region 化动态 Region 大小支持 2MB 到 32TB 堆NUMA 感知优化多 CPU 架构下的内存访问1.1.9 线上分析工具工具用途jmap生成堆转储dump、查看堆信息jstack查看线程堆栈、定位死锁jstat实时查看 GC 状态、类加载信息jcmd综合诊断命令JDK 7jconsole可视化监控jvisualvm性能分析、堆 dump 分析Arthas阿里开源在线诊断工具可在线查看方法调用、热更新MATEclipse 堆转储分析工具内存泄漏分析GC 日志-Xloggc:开启分析 GC 频率和停顿1.2 Java 并发编程1.2.1 AQSAbstractQueuedSynchronizer核心思想CLH 双向队列 CAS 改 statestate同步状态int通过 CAS 修改CLH 队列FIFO 双向链表管理等待线程独占模式只有一个线程能获取如 ReentrantLock共享模式多个线程可同时获取如 Semaphore、CountDownLatch基于 AQS 实现的同步器ReentrantLockSemaphoreCountDownLatchCyclicBarrierReentrantReadWriteLockFutureTask1.2.2 ReentrantLock核心特性可重入锁state表示重入次数0 表示未被占用支持公平锁new ReentrantLock(true)和非公平锁默认公平锁按队列顺序获取非公平锁允许插队性能更好与 synchronized 对比特性synchronizedReentrantLock实现层面JVM 内置CJDK 层面Java AQS释放方式自动释放手动unlock()中断支持不可中断lockInterruptibly()可中断超时获取不支持tryLock(timeout)支持条件变量wait/notifyCondition多条件性能相近相近1.2.3 CASCompare And Swap核心原理硬件级别原子操作通过 CPU 指令CMPXCHG实现三个参数内存地址 V、期望值 A、新值 B当 V 值 A 时将 V 更新为 B否则失败ABA 问题现象V 值从 A → B → ACAS 误认为未变化解决方案AtomicStampedReference带版本号stamp的原子引用AtomicMarkableReference带标记位mark的原子引用Unsafe 类提供底层 CAS 操作compareAndSwapInt、compareAndSwapObject等可直接操作内存allocateMemory、putInt等禁止直接使用JDK 9 限制访问1.2.4 Volatile两个语义可见性写操作立即刷新到主内存读操作从主内存读取禁止指令重排序内存屏障LoadLoad、StoreStore、LoadStore、StoreLoad适用场景状态标志位volatile boolean running单次读/写操作非复合操作如count不适用1.2.5 Atomic 包类说明AtomicInteger原子 intAtomicLong原子 longAtomicBoolean原子 booleanAtomicReference原子引用AtomicIntegerArray原子 int 数组AtomicStampedReference带版本号引用解决 ABAAtomicMarkableReference带标记引用1.2.6 LongAdder vs AtomicLongAtomicLongCAS 自旋高并发下冲突严重性能下降LongAdder分段累加Cell 数组各线程操作不同 Cell最后 sum 汇总适用场景LongAdder 适合写多读少AtomicLong 适合读多写少1.2.7 ThreadPoolExecutor核心参数corePoolSize核心线程数maximumPoolSize最大线程数keepAliveTime空闲线程存活时间unit时间单位workQueue任务队列ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueuethreadFactory线程工厂handler拒绝策略拒绝策略AbortPolicy默认抛出 RejectedExecutionExceptionCallerRunsPolicy调用者线程执行DiscardPolicy丢弃不抛异常DiscardOldestPolicy丢弃队列头部任务线程池满的原因与排查核心线程数过小任务队列过小或过大任务执行时间过长线程阻塞IO、锁等待1.2.8 ForkJoinPool分治思想大任务拆分为小任务并行执行后合并结果工作窃取Work-Stealing空闲线程从其他队列尾部窃取任务适用场景递归任务、大数组并行计算1.2.9 CompletableFuture核心方法supplyAsync/runAsync异步执行thenApply/thenAccept/thenRun串行依赖thenCombine/thenCompose组合依赖allOf/anyOf多任务聚合complete/completeExceptionally手动完成异步编排最佳实践使用自定义线程池避免共用ForkJoinPool.commonPool()合理设置超时completeOnTimeout/orTimeout1.2.10 StampedLock优化 ReentrantReadWriteLock乐观读锁不阻塞写操作三种锁模式writeLock写锁readLock读锁悲观tryOptimisticRead乐观读不阻塞写需验证 stamp1.2.11 CountDownLatch vs CyclicBarrier vs Semaphore vs Phaser同步器核心机制可重用典型场景CountDownLatch计数器递减至 0 释放❌等待多个任务完成CyclicBarrier等待所有线程到达屏障点✅多线程分段执行Semaphore许可证控制并发数✅限流、资源池Phaser动态注册/注销参与者✅多阶段并行任务1.3 JUC 源码1.3.1 ConcurrentHashMapJDK 1.8为什么 1.8 不用 SegmentSegment 继承 ReentrantLock锁粒度粗一个 Segment 锁一个 Hash 桶数组1.8 改用synchronized CAS锁粒度细化到单个桶Node 头节点更细粒度 → 更高并发度核心数据结构// 核心属性transientvolatileNodeK,V[]table;privatetransientvolatileNodeK,V[]nextTable;privatetransientvolatileintsizeCtl;privatetransientvolatileinttransferIndex;为什么 TreeBin当链表长度 8 时链表转为红黑树TreeBin包装 TreeNode红黑树查询复杂度 O(log n)避免长链表导致查询慢树化阈值 8退化阈值 6防止频繁转换为什么 ForwardNode扩容时已迁移的桶位置放置ForwardingNode指向nextTable用于扩容期间转发读写请求写操作遇到 ForwardNode协助扩容helpTransfer为什么 sizeCtl多状态控制变量-1正在初始化-(1 nThreads)正在扩容0默认值 0下次扩容阈值容量 * 0.75为什么 helpTransfer扩容期间写线程检测到 ForwardNode 时主动参与扩容提升扩容速度减少阻塞等待体现“所有线程都是 Worker”的设计思想1.3.2 其他 JUC 源码要点CopyOnWriteArrayList写时复制适合读多写少BlockingQueue 实现ArrayBlockingQueue有界数组、LinkedBlockingQueue有界链表、SynchronousQueue无存储、PriorityBlockingQueue优先级、DelayQueue延迟ConcurrentLinkedQueue无界非阻塞队列CAS 实现1.4 线上排查经验1.4.1 CPU 100% 排查流程top -H -p pid查看进程内各线程 CPU 占用printf %x\n tid将线程 ID 转为十六进制jstack pid | grep -A 20 tid_hex查看线程堆栈定位热点代码死循环、频繁 GC、锁竞争、正则匹配Arthasthread命令一键分析 CPU 高的线程1.4.2 Full GC 频繁排查jstat -gcutil pid 1000查看 GC 频率jmap -heap pid查看各代内存使用jmap -dump:live,formatb,fileheap.hprof pid导出堆快照MAT分析大对象、内存泄漏常见原因内存泄漏、大对象频繁进入老年代、元空间膨胀1.4.3 OOM 排查流程分析事故现场CPU、内存、日志通过top -p pid分析进程资源占用判断内存增长类型爆炸性增长 vs 缓慢增长jmap -dump导出堆快照MAT 分析Leak Suspects报告、Dominator Tree、GC Roots路径1.4.4 死锁排查jstack pid自动检测死锁会打印 “Found one Java-level deadlock”查看线程状态BLOCKED、WAITING分析锁持有和等待关系本篇内容覆盖了原大纲第一、二、三部分的 Java 基础、JVM 和 JUC 相关知识点。后续将继续补充 Spring 体系、数据库、Redis、MQ、微服务、分布式、高并发、架构能力、云原生、制造业、跨境电商、代码能力、线上排查等剩余部分。