高级Java工程师 · 模拟面试题集

60分钟实战版 · 含考察点/回答思路/追问/评分标准
面试专家团:欧阳锋 · 林墨 · 苏晴 · 陈方 | 2026年7月
📋 面试流程总览(60分钟节奏表)

以下为60分钟模拟面试的标准节奏安排,每道题的时间分配已包含面试官追问环节。

环节时长题目数考察重点建议节奏
1. 自我介绍3分钟表达逻辑、技术栈匹配度简洁有力,突出亮点
2. Java基础10分钟2题语言核心、集合、异常每题5分钟(含追问)
3. JVM与并发10分钟2题内存模型、GC、线程安全概念+实战各一题
4. Spring原理10分钟2题IoC/AOP、事务、循环依赖源码级理解优先
5. 分布式系统10分钟2题一致性、服务治理、分布式事务结合实际场景回答
6. 数据库与缓存10分钟2题索引优化、Redis、缓存穿透SQL+NoSQL结合
7. 项目经验10分钟2题技术选型、难点攻克、架构演进STAR法则回答
8. 反问环节5分钟候选人提问质量准备2-3个有深度的问题
合计60分钟12题
Java基础
第1题HashMap在JDK 7和JDK 8中的实现差异
考察点
  • 数据结构演变:数组+链表 → 数组+链表+红黑树
  • 扩容机制与rehash过程
  • 头插法与尾插法的区别及死循环问题
  • 树化阈值、退化阈值的理解
  • 对并发环境下HashMap安全性的认知
参考回答思路

首先点明JDK 7使用数组+链表(头插法),JDK 8改为数组+链表+红黑树(尾插法)。核心变化:① 链表长度≥8且数组长度≥64时树化,长度≤6时退化为链表;② 扩容时JDK 7需rehash计算新位置,JDK 8通过位运算(e.hash & oldCap)将链表拆分为高低位两条链表,性能更优;③ 头插法在多线程扩容时可能形成环形链表导致死循环,JDK 8改为尾插法规避此问题。最后补充:HashMap非线程安全,并发场景应使用ConcurrentHashMap。

可能追问
  • Q:树化阈值为什么是8?
    答:泊松分布,负载因子0.75下链表长度达到8的概率极低(约0.00000006),是时间和空间的平衡。
  • Q:红黑树相比链表解决了什么问题?
    答:将最差情况下的O(n)查找降为O(log n),防止哈希碰撞攻击。
  • Q:ConcurrentHashMap在JDK 8中如何保证线程安全?
    答:使用synchronized+CAS替代JDK 7的Segment分段锁,锁粒度更细。
评分标准
档次表现分数
S档能清晰对比JDK 7/8差异,准确描述树化条件、扩容优化、并发问题,能展开到ConcurrentHashMap9-10分
A档能说出主要差异(红黑树、尾插法),但细节不够深入7-8分
B档仅知道HashMap有红黑树优化,说不清具体变化5-6分
C档回答零散,对HashMap底层结构理解模糊0-4分
第2题String、StringBuilder、StringBuffer的区别与底层实现
考察点
  • String不可变性的底层实现(final char[] / byte[])
  • 字符串常量池与intern()机制
  • StringBuilder与StringBuffer的继承关系
  • 线程安全性差异及性能对比
  • 字符串拼接的编译期优化
参考回答思路

先给出结论:String不可变,StringBuilder和StringBuffer可变。String底层在JDK 9之前是final char[],JDK 9之后改为byte[] + coder字段(LATIN1/UTF16),节省空间。不可变性带来线程安全、hash缓存、常量池复用等好处。StringBuilder和StringBuffer都继承AbstractStringBuilder,底层也是可变byte[]。区别在于StringBuffer的方法加了synchronized,线程安全但性能较低。补充:字符串常量池在JDK 7之后从方法区移到了堆中;使用+拼接字符串时,编译器会优化为StringBuilder.append(),但在循环中拼接仍会创建多个StringBuilder对象,建议手动使用StringBuilder。

可能追问
  • Q:new String("abc")创建了几个对象?
    答:若常量池已有"abc"则创建1个堆对象;若没有则创建2个(常量池1个+堆1个)。
  • Q:为什么JDK 9要把char[]改成byte[]?
    答:大多数String是Latin-1编码(一个字节),char[]每个字符占2字节浪费空间,byte[]+编码标识可以节省约50%内存。
  • Q:String.intern()在JDK 6和JDK 7+的区别?
    答:JDK 6 intern将字符串拷贝到永久代;JDK 7+只在常量池中记录首次出现的堆引用。
评分标准
档次表现分数
S档能深入底层(byte[]+coder、常量池位置变化、编译优化),举例说明性能差异9-10分
A档能说清三者的区别和适用场景,了解底层是char[]/byte[]7-8分
B档仅知道String不可变、StringBuffer线程安全,底层实现不清晰5-6分
C档概念混淆,说不出底层实现0-4分
JVM与并发编程
第3题JVM垃圾回收机制——CMS和G1的回收过程及适用场景
考察点
  • CMS回收的四个阶段(初始标记→并发标记→重新标记→并发清除)
  • CMS的缺点:浮动垃圾、内存碎片化、CPU敏感
  • G1的Region划分与垃圾回收机制
  • G1的Young GC、Mixed GC与并发标记周期
  • 停顿预测模型与-XX:MaxGCPauseMillis参数
  • JDK 9之后CMS被废弃的原因
参考回答思路

先说明GC算法的演进:Serial→Parallel→CMS→G1→ZGC。CMS:以最短停顿时间为目标,四个阶段中只有初始标记和重新标记需要STW。缺点是:①并发阶段占用CPU导致吞吐量下降;②并发清除时产生浮动垃圾;③基于标记-清除算法,产生内存碎片,最终触发Full GC时使用Serial Old单线程回收,停顿时间极长。G1:将堆划分为2048个Region,每个Region可以是Eden/Survivor/Old/Humongous。G1的GC分为Young GC和Mixed GC。G1的停顿预测模型根据历史数据估算回收指定Region所需时间,尽量满足用户设定的停顿目标。JDK 9将G1设为默认GC,CMS被标记为Deprecated。

可能追问
  • Q:G1的Remembered Set是什么?
    答:每个Region维护一个RSet,记录其他Region对该Region中对象的引用,避免全堆扫描。
  • Q:什么是Humongous Region?
    答:当对象大小超过Region大小的50%时,直接分配到Humongous Region,GC时直接回收。
  • Q:ZGC相比G1的核心优势?
    答:ZGC使用染色指针+读屏障,几乎不STW(<10ms),支持TB级堆。
评分标准
档次表现分数
S档能完整描述CMS和G1的回收阶段、优缺点、适用场景,能对比ZGC9-10分
A档能说清CMS四个阶段和G1的Region机制,但细节不够7-8分
B档知道CMS和G1的区别,但说不清具体回收过程5-6分
C档只能说出几种GC名称,不理解原理0-4分
第4题volatile关键字的内存语义及其在DCL中的作用
考察点
  • volatile的可见性:对volatile变量的写立即对其他线程可见
  • volatile的有序性:禁止指令重排序(内存屏障)
  • volatile不保证原子性
  • DCL中volatile的作用:防止new Singleton()的指令重排序
  • happens-before规则与内存屏障
参考回答思路

首先明确volatile的两大语义:可见性和有序性。可见性通过缓存一致性协议(如MESI)实现,写volatile变量时会强制刷新到主存,读时从主存读取。有序性通过插入内存屏障实现:写volatile变量前插入StoreStore屏障,写后插入StoreLoad屏障;读volatile变量后插入LoadLoad和LoadStore屏障。DCL单例:instance = new Singleton()在字节码层面分为三步——①分配内存 ②初始化对象 ③将引用指向内存地址。若不加volatile,②和③可能被重排序,导致另一个线程拿到未初始化完成的对象。volatile禁止了这种重排序。

可能追问
  • Q:volatile和synchronized的区别?
    答:volatile是轻量级同步,仅保证可见性和有序性,不保证原子性;synchronized保证互斥性、可见性和有序性。
  • Q:什么是内存屏障?有哪些类型?
    答:LoadLoad、StoreStore、LoadStore、StoreLoad四种。StoreLoad是最重的屏障,volatile写后插入的就是StoreLoad。
  • Q:除了DCL,volatile还有哪些经典应用场景?
    答:状态标志位(如boolean running)、双重检查锁的DCL、CAS循环中的变量。
评分标准
档次表现分数
S档能深入内存屏障、happens-before、DCL指令重排序细节,结合实际场景9-10分
A档能说清可见性和有序性,能解释DCL中volatile的作用7-8分
B档知道volatile能保证可见性,但对有序性和DCL理解不深5-6分
C档概念模糊,说不清volatile和synchronized的区别0-4分
Spring原理
第5题Spring IoC容器的启动流程与Bean的生命周期
考察点
  • IoC容器初始化核心流程:Resource定位→BeanDefinition加载→注册→后处理
  • BeanFactoryPostProcessor和BeanPostProcessor的执行时机
  • Bean的完整生命周期(从实例化到销毁)
  • Spring如何解决循环依赖(三级缓存)
  • Aware接口的作用
参考回答思路

IoC容器启动:①通过ResourceLoader加载配置;②BeanDefinitionReader解析配置生成BeanDefinition;③BeanDefinition注册到BeanFactory;④执行BeanFactoryPostProcessor。Bean生命周期:实例化→属性赋值→Aware接口回调→BeanPostProcessor前置处理→InitializingBean.afterPropertiesSet()/init-method→BeanPostProcessor后置处理→Bean就绪→容器关闭时执行DisposableBean.destroy()/destroy-method。循环依赖:Spring使用三级缓存解决——①singletonObjects(一级,成品Bean);②earlySingletonObjects(二级,提前曝光的半成品);③singletonFactories(三级,ObjectFactory)。

可能追问
  • Q:为什么需要三级缓存,二级不够吗?
    答:二级缓存可以解决循环依赖,但无法支持AOP代理。三级缓存存储ObjectFactory,在需要时通过getEarlyBeanReference()创建代理对象。
  • Q:prototype作用域为什么不能解决循环依赖?
    答:prototype Bean不缓存,每次请求都创建新实例,无法使用三级缓存。
  • Q:@Autowired和@Resource的区别?
    答:@Autowired按类型注入(byType),配合@Qualifier按名称;@Resource默认按名称注入(byName),由JSR-250规范定义。
评分标准
档次表现分数
S档能完整描述IoC启动流程+Bean生命周期+三级缓存解决循环依赖的源码级细节9-10分
A档能说清Bean生命周期和三级缓存机制,但源码细节不够7-8分
B档知道Bean生命周期步骤,对循环依赖理解停留在概念层面5-6分
C档只能说出IoC是控制反转,不理解具体流程0-4分
第6题Spring事务的传播行为与实现原理
考察点
  • 七种事务传播行为(REQUIRED/REQUIRES_NEW/NESTED等)
  • @Transactional注解的底层实现(AOP+TransactionInterceptor)
  • 事务失效的常见场景
  • 编程式事务与声明式事务的对比
  • 事务隔离级别的实现
参考回答思路

先列举最常用的三种传播行为:REQUIRED(默认,有则加入无则创建)、REQUIRES_NEW(挂起当前事务创建新事务)、NESTED(嵌套事务,使用Savepoint回滚点)。实现原理:@Transactional通过AOP生成代理对象,TransactionInterceptor在目标方法前后织入事务逻辑。事务失效场景:①@Transactional加在private方法上;②同类方法内部调用(this.method()绕过代理);③异常被catch后未抛出;④rollbackFor未指定,且抛出的不是RuntimeException;⑤数据库引擎不支持事务(如MyISAM)。

可能追问
  • Q:REQUIRES_NEW和NESTED的区别?
    答:REQUIRES_NEW是完全独立的事务,互相不影响;NESTED是嵌套事务,内层回滚可只回滚到Savepoint,外层仍可提交。
  • Q:事务隔离级别中MySQL默认是什么?
    答:MySQL默认REPEATABLE READ,通过MVCC + Next-Key Lock解决幻读。
  • Q:如何使用编程式事务?
    答:注入PlatformTransactionManager,调用TransactionTemplate.execute()或手动begin/commit/rollback。
评分标准
档次表现分数
S档能说出7种传播行为,深入AOP实现原理,列举5种以上事务失效场景9-10分
A档能说清常用传播行为,了解实现原理,能说出3种失效场景7-8分
B档知道REQUIRED/REQUIRES_NEW,对实现原理理解模糊5-6分
C档只会用@Transactional,不理解传播行为和失效原因0-4分
分布式系统
第7题分布式事务的常见解决方案及适用场景
考察点
  • 两阶段提交(2PC)的原理与缺点
  • TCC(Try-Confirm-Cancel)模式
  • 本地消息表与可靠消息最终一致性
  • Seata AT模式的实现机制
  • 最大努力通知与事务消息(RocketMQ)
  • CAP理论与BASE理论的理解
参考回答思路

先引出CAP理论:分布式系统无法同时满足一致性、可用性和分区容错性。BASE理论强调最终一致性。解决方案对比:①2PC——强一致性,但存在同步阻塞、单点故障问题;②TCC——对业务侵入性强,需要实现Try/Confirm/Cancel三个接口;③本地消息表+MQ——将分布式事务转化为本地事务+消息队列;④Seata AT——自动生成反向SQL实现回滚,对业务代码无侵入。推荐方案:高并发场景用TCC或Seata AT;最终一致性场景用事务消息(RocketMQ)。

可能追问
  • Q:Seata AT模式如何实现自动回滚?
    答:Seata AT在执行业务SQL前记录前后镜像(Before Image/After Image),回滚时生成反向SQL。
  • Q:RocketMQ事务消息的实现流程?
    答:发送半消息→执行本地事务→根据本地事务结果commit/rollback半消息→如果长时间未commit则回查。
  • Q:TCC的空回滚和幂等问题如何处理?
    答:通过事务日志记录Try阶段是否执行,Cancel时检查日志避免空回滚;通过唯一事务ID保证幂等。
评分标准
档次表现分数
S档能对比4种以上方案,深入原理(如Seata AT的镜像机制),结合CAP分析9-10分
A档能说清2PC/TCC/消息表三种方案及适用场景7-8分
B档知道分布式事务概念,能说出2-3种方案但理解不深5-6分
C档只知道CAP理论,说不清具体实现方案0-4分
第8题服务治理——设计高可用的微服务架构
考察点
  • 注册中心选型(Nacos/Eureka/Consul/Zookeeper)及CP/AP权衡
  • 配置中心的实现与动态刷新机制
  • 网关的核心功能(路由、鉴权、限流、灰度发布)
  • 熔断降级的实现(Sentinel/Hystrix/Resilience4j)
  • 服务间调用(Feign/OpenFeign + 负载均衡)
  • 可观测性(日志、指标、链路追踪)
参考回答思路

推荐技术栈:Spring Cloud Alibaba(Nacos + Sentinel + Gateway + SkyWalking)。注册中心选Nacos:支持CP和AP模式切换。配置中心:Nacos Config + @RefreshScope实现动态刷新。网关:Spring Cloud Gateway基于WebFlux,非阻塞IO。熔断降级:Sentinel支持流控(QPS/线程数)、熔断(慢调用/异常比例/异常数)、热点参数限流。可观测性:SkyWalking + Prometheus + ELK + Micrometer。

可能追问
  • Q:Nacos的CP/AP模式如何切换?
    答:通过ephemeral参数,临时实例(AP模式,心跳检测)和持久化实例(CP模式,Raft协议)。
  • Q:Sentinel的滑动窗口限流原理?
    答:将时间划分为多个小窗口,每个窗口统计QPS,滑动时淘汰旧窗口数据,精度比固定窗口高。
  • Q:如何实现灰度发布?
    答:网关层根据Header/Cookie/权重路由到不同版本的服务实例;Nacos支持元数据路由。
评分标准
档次表现分数
S档能设计完整架构,深入选型对比,考虑可观测性9-10分
A档能说出核心组件选型和功能,架构设计合理7-8分
B档知道注册中心、网关、熔断的概念,但选型和原理不清晰5-6分
C档只听说过微服务,说不出具体组件0-4分
数据库与缓存
第9题MySQL索引的底层实现与优化策略
考察点
  • B+树索引的结构与优势(相比B树、红黑树、哈希索引)
  • 聚簇索引与非聚簇索引的区别
  • 最左前缀原则与索引下推(ICP)
  • 覆盖索引与回表查询
  • 索引失效场景与慢查询优化
  • EXPLAIN执行计划分析
参考回答思路

B+树特点:非叶子节点只存索引不存数据,叶子节点存数据且形成有序链表。相比B树,B+树I/O次数更少,范围查询更高效。聚簇索引:InnoDB的主键索引就是聚簇索引,叶子节点存储整行数据。非聚簇索引(二级索引)叶子节点存储主键值,查询时需要回表。最左前缀:联合索引(a,b,c)中,查询条件必须从a开始匹配。索引下推(ICP):MySQL 5.6引入,在索引遍历过程中对索引包含的字段先做过滤,减少回表次数。

可能追问
  • Q:如何根据EXPLAIN的type字段判断SQL性能?
    答:system>const>eq_ref>ref>range>index>ALL,至少要达到range级别。
  • Q:什么是MRR(Multi-Range Read)?
    答:将随机I/O转化为顺序I/O,先排序主键再回表。
  • Q:1000万数据如何优化分页查询?
    答:使用子查询或延迟关联,先查主键再关联原表。
评分标准
档次表现分数
S档能深入B+树结构、ICP、MRR等高级特性,能结合实际SQL优化案例9-10分
A档能说清B+树、聚簇索引、最左前缀,能分析索引失效场景7-8分
B档知道B+树和索引类型,但对优化策略理解不深5-6分
C档只知道索引能加速查询,说不清底层原理0-4分
第10题Redis的高可用架构与缓存一致性方案
考察点
  • Redis高可用方案:主从+哨兵 vs Redis Cluster
  • 哨兵模式的故障转移过程
  • Redis Cluster的数据分片(16384个槽位)与哈希Tag
  • 缓存穿透、缓存击穿、缓存雪崩的定义与解决方案
  • 缓存与数据库一致性方案(Cache Aside / 延迟双删)
  • Redis持久化:RDB vs AOF vs 混合持久化
参考回答思路

高可用方案:主从+哨兵适合数据量<10G的场景,哨兵通过Raft协议选举Leader;Redis Cluster适合数据量大的场景,自动分片。三大缓存问题:①缓存穿透——布隆过滤器+缓存空值;②缓存击穿——互斥锁+逻辑过期;③缓存雪崩——过期时间加随机值+多级缓存。缓存一致性:推荐Cache Aside Pattern——读时先读缓存,未命中则读DB并回写缓存;写时先更新DB再删除缓存(延迟双删)。

可能追问
  • Q:Redis Cluster中数据如何迁移?
    答:通过reshard,将槽位从源节点迁移到目标节点,使用migrate命令迁移key。
  • Q:Redis的过期删除策略?
    答:惰性删除(访问时检查过期)+ 定期删除(每秒10次,随机抽查20个key)。
  • Q:如何保证Redis和MySQL的最终一致性?
    答:使用Binlog+MQ异步同步(Canal监听Binlog变更→MQ→消费更新Redis),或使用延迟双删+重试机制。
评分标准
档次表现分数
S档能深入哨兵/Cluster原理,清晰对比缓存一致性方案,有实战经验9-10分
A档能说清三大缓存问题和高可用方案,了解一致性方案7-8分
B档知道缓存穿透/击穿/雪崩,但对高可用和一致性理解不深5-6分
C档只会用Redis做缓存,说不清高可用和一致性方案0-4分
项目经验与综合能力
第11题用STAR法则介绍最有成就感的项目
考察点
  • 技术深度与广度:能否清晰描述技术选型理由
  • 架构设计能力:系统分层、模块划分、关键设计决策
  • 问题解决能力:遇到的最大难点及解决过程
  • 数据量化能力:用数据说明项目成果
  • 团队协作与领导力:在团队中的角色和贡献
参考回答思路

建议按STAR法则组织回答:Situation(项目背景)→ Task(你的任务)→ Action(具体行动)→ Result(量化结果)。示例框架:"我在XX电商公司负责订单系统的重构,原系统在双11大促时QPS仅2000,响应时间超过5秒。我主导了系统拆分、引入Redis缓存、使用RocketMQ异步削峰、数据库分库分表。重构后系统支撑QPS 20000+,响应时间降至200ms以下,双11当天零故障。"重点突出:技术选型理由、对比数据、踩坑经验。

可能追问
  • Q:分库分表后如何实现跨库分页查询?
    答:将查询分发到所有分片,在应用层归并排序,或者使用Elasticsearch做搜索。
  • Q:订单系统如何保证幂等?
    答:使用订单号作为唯一键,插入时先查是否存在;MQ消费端使用去重表。
  • Q:如果让你重新设计,你会做什么改进?
    答:可以引入单元化架构、多活部署等。
评分标准
档次表现分数
S档STAR完整,数据量化清晰,技术选型有深度对比,有踩坑经验9-10分
A档STAR完整,有数据支撑,技术描述准确7-8分
B档STAR结构不完整,缺乏数据量化,技术描述较浅5-6分
C档流水账式描述,缺乏重点和数据支撑0-4分
第12题线上CPU飙升100%的排查思路
考察点
  • 问题排查方法论:从现象到根因的逐步定位
  • Linux常用工具:top/htop、jstack、jstat、jmap、arthas
  • 常见原因分析:死循环、频繁GC、线程争抢、死锁
  • 监控告警体系的建设意识
  • 应急预案与止损措施
参考回答思路

第一步(定位进程):使用top -c找到CPU最高的Java进程PID。第二步(定位线程):top -Hp 找到CPU最高的线程TID,转为十六进制。第三步(定位代码):jstack | grep -A 30 <十六进制TID>,找到对应的线程堆栈。第四步(分析根因):常见情况——①死循环;②频繁Full GC;③线程死锁;④锁竞争激烈。第五步(止损与修复):先重启或摘除节点止损,再分析代码修复,最后补充监控告警。

可能追问
  • Q:如果jstack看不到线程信息怎么办?
    答:使用arthas的thread命令,或pstack查看原生线程栈。
  • Q:如何分析内存泄漏?
    答:jmap -dump:live,format=b,file=heap.hprof ,然后用MAT或JProfiler分析GC Root引用链。
  • Q:如果CPU不高但内存持续增长怎么办?
    答:使用jstat -gcutil观察老年代增长趋势,配合jmap dump分析大对象。
评分标准
档次表现分数
S档排查步骤完整,能熟练使用工具,有实际线上排查经验,能说出止损措施9-10分
A档能说出排查流程和常用命令,定位思路清晰7-8分
B档知道用top和jstack,但排查步骤不完整5-6分
C档只会重启服务器,缺乏系统排查思路0-4分
📊 综合评分表
题目环节满分得分备注
第1题 HashMap实现差异Java基础10
第2题 String/StringBuilder/StringBufferJava基础10
第3题 CMS与G1垃圾回收JVM与并发10
第4题 volatile与DCLJVM与并发10
第5题 IoC与Bean生命周期Spring原理10
第6题 事务传播行为Spring原理10
第7题 分布式事务分布式系统10
第8题 微服务架构设计分布式系统10
第9题 MySQL索引数据库缓存10
第10题 Redis高可用与缓存一致性数据库缓存10
第11题 项目经验(STAR)项目经验10
第12题 CPU飙升排查项目经验10
合计120
💡 面试建议