Imported from yuecao365/Interviewer-skills (
skills/java/SKILL.md). Install upstream withnpx skills add yuecao365/Interviewer-skills --skill java. Copyright stays with the author.
面试官在意什么
Java 后端是国内互联网公司体量最大的后端岗位,日常是在 Spring Boot / Spring Cloud 或 Dubbo 体系里写业务服务、接中间件、处理线上问题。真实面试里 Java 方向有一条非常稳定的主线:JVM 内存与 GC、并发(线程池、锁、JUC 工具)、Spring 原理(IoC、AOP、事务)、持久层(MyBatis/JPA 与连接池)、微服务组件(注册中心、网关、配置中心、RPC)。这些题被问烂了,所以面试官最在意的不是候选人能不能背出 CMS 和 G1 的区别,而是三件事:一是遇到 OOM、CPU 飙高、接口变慢、线程池打满时有没有真实排查过,用什么工具、看什么数据;二是对 Spring 这类"魔法"背后的机制是否真的理解,能否解释自己项目里某个注解为什么不生效;三是并发代码能不能写对,能不能指出一段代码里的竞态。
校招侧重基础:集合源码(HashMap、ConcurrentHashMap)、synchronized 与 ReentrantLock、JVM 内存区域与垃圾回收基本流程、Spring Bean 生命周期、手写线程安全的单例或生产者消费者。社招侧重排查与设计:线上 Full GC 频繁怎么定位、线程池参数怎么定、@Transactional 失效的场景、分布式锁的坑、微服务之间调用超时链路、JDK 17/21 的虚拟线程对现有模型的影响。一线大厂近年明显减少了纯八股,改为"给你一段代码/一个现象,说问题在哪"。
怎么问才像这个方向的面试官:
- 架构与方法论(缓存一致性、消息队列、限流降级)交给 backend 包,本包专注 Java 生态的实现细节与排查手段。
- 八股必须落到现象:任何原理题都要配一个"线上会怎么表现""你怎么验证"的追问,能背不能用的要标记。
- 代码级追问:并发、事务、集合相关主题优先给一段代码或一个现象让候选人找问题,而不是让他复述概念。
- 按 JDK 版本与项目规模出题:还在 JDK 8 的项目不追虚拟线程;小项目不追 ZGC 与容器内存分配,但必须会读 GC 日志与线程栈。
- 2026 年 Java 后端的生产基线是 JDK 21 / 25 与 Spring Boot 3 / 4:虚拟线程接管 IO 密集服务后线程池调优这类老题会反过来问"什么时候不该用虚拟线程"(pinning、CPU 密集、ThreadLocal 膨胀);紧凑对象头、分代 ZGC、Spring 的 HTTP Service Client 与空安全注解是新的追问点;接大模型的服务会追 Spring AI 一类集成的超时、重试与成本控制。
项目 / 实习怎么深挖
简历上出现下面这类经历时从哪里切、追什么。追到候选人能说出机制、数字的来源与一次真实的故障或取舍才算实;只有框架名与结论、说不出自己那一段的,记为危险信号。通用的追问方法见 project-deep-dive。
- 简历出现 JVM 调优 → 追调之前的 GC 指标、改了什么参数、调完的对比数据、有没有先排除内存泄漏;说不出 GC 日志内容的要标记
- 简历出现线程池 / 并发优化 → 追参数怎么定、监控了什么、有没有出过任务堆积或死锁
- 简历出现 Spring Cloud / Dubbo → 追注册中心是哪个、优雅下线怎么做、超时重试在哪一层配、服务间调用出过什么问题
- 简历出现 MyBatis / JPA → 追连接池大小与依据、慢 SQL 怎么发现、事务范围多大、有没有 N+1
- 简历出现 Redis 分布式锁 → 追锁过期怎么处理、释放怎么保证是自己的、主从切换考虑过没有
- 简历出现 Netty / 自研 RPC → 追线程模型、编解码与粘包、直接内存管理、空闲检测与重连
- 简历出现 JDK 17/21 升级 → 追迁移遇到的问题(模块化、反射限制、Jakarta 包名)、虚拟线程是否用了、收益是什么
- 简历出现"接口性能优化" → 追用什么工具定位(Arthas、profiler、trace)、瓶颈是什么、优化前后的 P99
常见失守与危险信号
- JVM 内存结构与 OOM 排查:只知道 -Xmx;分不清 JVM OOM 与容器 OOMKilled;不知道 NIO/Netty 会用直接内存
- GC 选型与调优:背收集器名字但没看过 GC 日志;把所有问题都归为"堆太小";不知道 G1 大对象(Humongous)的问题
- 线程池设计与故障:用 Executors.newFixedThreadPool 而不知道是无界队列;参数按"CPU 核数 + 1"背公式却不看任务类型;不知道 ThreadLocal 在线程池里会串
- 锁与并发工具:认为 volatile 能保证原子性;不知道 ConcurrentHashMap 的 size 与复合操作不是原子;从没用 jstack 看过线程状态
- Java 内存模型与可见性:把 volatile 当轻量锁;不知道 JIT 会做重排与提升;说不出 happens-before 的任何一条规则
- 虚拟线程与新版本 JDK:认为虚拟线程等于协程无脑更快;不知道 pinning;不知道数据库连接池仍是瓶颈
- Spring IoC / AOP 原理与失效场景:背出三级缓存但说不清每一级存什么;不知道自调用绕过代理;把 @Transactional 放在 private 方法上
- Spring Boot 与生态实践:不知道 spring.factories / AutoConfiguration.imports;配置来源顺序说不清;从没看过启动日志
- 持久层:MyBatis / JPA 与连接池:连接池设成几百认为越大越好;不知道 MyBatis 一级缓存在 Spring 事务下的行为;JPA 项目全靠 findAll 后内存过滤
- 微服务组件:注册发现、配置、网关、RPC:只会配置 starter 不知道原理;不知道注册中心的 AP/CP 差别;没处理过优雅停机
- 分布式锁与缓存实践(Java 视角):del 锁不校验持有者;不知道看门狗续期;认为 RedLock 是银弹
- 性能排查工具与方法:只会重启;不知道 top -H 配合 jstack 找线程;没用过 Arthas 或 profiler
- 集合与基础源码:能背 HashMap 源码但说不出自己项目里哪里用错了集合;不知道 ArrayList 遍历删除的坑
常考主题清单
只列名字、阶梯与答实的标志,作"问到哪一层算实"的参考;问哪些、问几道由这份 JD 与这份简历定,不是配额。
JVM 内存结构与 OOM 排查
- 阶梯:堆、栈、方法区/元空间、直接内存各放什么 → 对象分配与晋升、TLAB、逃逸分析与标量替换 → 各种 OOM(heap、metaspace、direct、unable to create native thread)各自的典型原因与排查手段 → 堆大小、容器内存限制、堆外内存之间怎么分配
- 答实的标志:会用 jmap/jcmd 导 heap dump 并用 MAT 看支配树;知道 MaxDirectMemorySize、元空间、线程栈、JIT 代码缓存都占容器内存;容器环境下用百分比参数(MaxRAMPercentage);能说出一次真实的内存泄漏定位(如 ThreadLocal 未清理、静态集合、连接未关)
GC 选型与调优
- 阶梯:分代假设与常见收集器(Parallel、CMS、G1、ZGC)各自的目标 → G1 的 Region、Mixed GC、停顿目标怎么工作,ZGC 的并发与染色指针 → Young GC 频繁、Full GC 频繁、单次停顿过长各自怎么定位 → 吞吐优先还是延迟优先,什么规模该上 ZGC,调参与改代码哪个先做
- 答实的标志:会读 GC 日志中的回收前后各代大小、晋升失败、并发模式失败;知道 Full GC 常见触发(老年代满、元空间满、System.gc、晋升失败);提到用 jstat/GC 日志分析工具看趋势;先看是否有内存泄漏或大对象分配再调参
线程池设计与故障
- 阶梯:为什么用线程池、核心参数各是什么 → 任务提交流程(核心线程→队列→最大线程→拒绝)、为什么无界队列危险 → 线程池打满、任务堆积、线程泄漏、父子任务死锁的排查 → IO 密集与 CPU 密集怎么定参数、多个线程池的隔离与监控
- 答实的标志:解释队列先于最大线程;给线程池命名并暴露活跃数/队列长度指标;拒绝策略按业务选(丢弃、调用者执行、降级);提到 CompletableFuture 默认用 ForkJoinPool 的坑;知道父任务等子任务且共用池会死锁
锁与并发工具
- 阶梯:synchronized 与 ReentrantLock 的区别 → 锁升级、AQS 的队列与 state、CAS 与 ABA → 死锁怎么用 jstack 定位、锁竞争导致吞吐下降怎么优化 → 锁粒度、读写锁、无锁结构、分段与 LongAdder 的适用边界
- 答实的标志:能画出 AQS 的等待队列;知道 compute/merge 这类原子复合操作;锁竞争用分段、缩小临界区、读写分离解决;能解释 happens-before 与内存可见性
Java 内存模型与可见性
- 阶梯:volatile 解决什么问题 → JMM 的 happens-before 规则、指令重排、内存屏障 → 双重检查锁为什么需要 volatile、什么代码在 x86 上跑对了到 ARM 上出错 → 什么时候需要关心 JMM,final 与安全发布
- 答实的标志:区分原子性、可见性、有序性;知道 AtomicXxx 与 VarHandle;能解释安全发布与不可变对象的价值
虚拟线程与新版本 JDK
- 阶梯:JDK 21 虚拟线程解决什么问题 → 与平台线程的映射、载体线程、pinning(synchronized 内阻塞)→ 上了虚拟线程后线程池、ThreadLocal、数据库连接池怎么办 → 什么业务值得迁、迁移风险与收益
- 答实的标志:知道 synchronized 块内阻塞会 pin 载体线程(JDK 24 前);虚拟线程不该池化但下游资源仍需限流;ThreadLocal 在海量虚拟线程下的内存问题与 ScopedValue;提到 record、sealed、pattern matching 等语言特性的实际使用
Spring IoC / AOP 原理与失效场景
- 阶梯:IoC 与 DI 解决什么问题 → Bean 生命周期、三级缓存解决循环依赖、代理生成(JDK 动态代理 vs CGLIB)→ @Transactional / @Async / @Cacheable 不生效的原因排查 → 什么逻辑该用 AOP、什么不该,代理带来的性能与可调试性代价
- 答实的标志:解释代理对象与目标对象的差别;知道事务传播行为与回滚规则(默认只回滚 RuntimeException);能说出 BeanPostProcessor 的扩展点与自己用过的场景;提到 Spring Boot 自动装配的条件注解与排查方式(条件评估报告)
Spring Boot 与生态实践
- 阶梯:自动装配怎么工作 → Starter 的机制、配置优先级、Actuator 暴露了什么 → 启动慢、Bean 冲突、配置被覆盖的排查 → Spring Boot 3 / Spring 6 的变化(Jakarta、AOT、GraalVM native)值不值得迁
- 答实的标志:会用 Actuator 的 startup 端点或 ApplicationStartup 看启动耗时;懒加载与异步初始化;理解 @ConditionalOnMissingBean 与用户覆盖默认配置的机制
持久层:MyBatis / JPA 与连接池
- 阶梯:MyBatis 与 JPA 怎么选 → MyBatis 的一二级缓存、动态 SQL、批量插入,JPA 的 N+1、懒加载与 open-in-view → 连接池(HikariCP)耗尽、慢 SQL 拖垮连接池、事务内做 RPC 的排查 → 连接池大小怎么定、读写分离在哪一层做、ORM 与手写 SQL 的边界
- 答实的标志:连接池大小与数据库核心数、事务时长的关系;用连接池的 leak detection 或慢事务监控;大事务拆小、事务里不做 IO;批量操作用 rewriteBatchedStatements 或手写 batch;知道 JPA 的脏检查与 flush 时机
微服务组件:注册发现、配置、网关、RPC
- 阶梯:Spring Cloud 与 Dubbo 各自的定位 → 注册中心(Nacos/Eureka/ZK)的一致性模型、心跳与摘除、配置热更新原理 → 服务下线流量仍打进来、配置推送不生效、网关成为瓶颈的排查 → 服务网格 vs SDK 模式、跨语言与统一治理的取舍
- 答实的标志:先摘注册再停容器、等待在途请求、客户端缓存刷新周期;Dubbo/gRPC 的序列化、负载均衡、重试语义;网关的限流鉴权与路由热更新;配置中心的灰度与回滚
分布式锁与缓存实践(Java 视角)
- 阶梯:为什么 synchronized 在集群里没用 → Redis 分布式锁(SET NX PX、Redisson 看门狗)与 ZK 锁的差别 → 锁过期业务没执行完、主从切换锁丢失、锁误删的处理 → 什么场景其实不需要分布式锁(幂等、乐观锁、队列串行化)
- 答实的标志:唯一值 + Lua 释放;fencing token 或数据库版本号做最终保护;能说出何时改用数据库乐观锁;Spring Cache 注解与 Redis 结合的过期、穿透处理
性能排查工具与方法
- 阶梯:CPU 高怎么查、内存高怎么查 → jstack/jmap/jstat/jcmd、Arthas、async-profiler 各看什么 → 接口 P99 高但平均正常、偶发抖动、特定机器慢的定位思路 → 排查工具的线上安全性(dump 停顿、采样开销),什么该常态化监控
- 答实的标志:top -H → 线程 ID 转十六进制 → jstack 匹配;Arthas 的 thread/trace/watch;async-profiler 火焰图;知道 heap dump 会 STW 要挑机器与时机;结合 GC 日志与监控看趋势
集合与基础源码
- 阶梯:HashMap 的结构与扩容 → 红黑树转换阈值、并发下的问题、ConcurrentHashMap 的分段与 CAS → 集合导致的性能与内存问题(大 Map 扩容抖动、fail-fast、内存放大)→ 什么时候需要关心这些,什么时候该用专用结构
- 答实的标志:解释扩容与哈希冲突;预设容量;布隆过滤器、位图、外部去重;知道 String、包装类型的内存占用