2026秋招 Java 大厂面试的准备,最怕的不是八股文背不完,而是背完 Spring 三级缓存、JVM 内存模型、MySQL 索引、Redis 分布式锁和 Netty 线程模型之后,仍然答不出一套完整的调用链路。面试官真正想看的,是你在一个具体场景里能不能把源码、参数、报错日志、架构取舍串起来。与其把时间全部花在“背答案”上,不如把 Spring、JVM、MySQL、Redis、Netty 这五条技术主线重新梳理一遍,让每个知识点都落到项目场景里。
下面按五条主线的复习顺序展开,每条线都会给出核心概念、常见考点、典型代码或命令、报错排查思路,以及面试回答时的展开方式。最后再给出一套每天都能用的复习计划和面试前检查清单,适合从零准备、也适合刷完一轮题后做复盘的人。
1. 2026 秋招 Java 大厂面试的考点怎么拆解
1.1 大厂面试更关注“链路能力”而不是单个知识点
校招面试和平时考试不一样。考试考的是“记住了没有”,面试考的是“遇到问题能不能想明白”。
举一个最典型的例子。面试官问“Redis 分布式锁怎么做”,如果你只回答SET key value EX 10 NX,这只是记住了命令。更好的回答是把链路讲出来:为什么需要分布式锁,setnx 解决了什么,expire 解决了什么,释放锁时为什么不能直接DEL,业务执行时间超过锁过期时间怎么办,主从切换时锁会不会丢。每多回答一层,就多展示一个维度的能力。
2026 秋招的竞争点不会只是“背得全”,而是“能串联”。建议在准备每个知识点时,都往三个方向追问:
- 这个方案解决了什么问题。
- 这个方案在什么场景下会失效。
- 生产环境出现问题时,通过哪个日志或命令能找到根因。
1.2 五条主线的优先级划分
Spring、JVM、MySQL、Redis、Netty 五条线并不是平均用力。不同岗位倾向不同,但校招常考频率存在明显差异。
| 技术线 | 高频考点 | 典型深度 | 复习优先级 |
|---|---|---|---|
| Spring | IoC、AOP、三级缓存、事务、Spring MVC 流程 | 源码级 | 高 |
| JVM | 内存区域、垃圾回收、类加载、JIT、OOM 排查 | 原理加参数 | 高 |
| MySQL | 索引、事务隔离、锁、SQL 调优、主从 | 可现场写 SQL | 极高 |
| Redis | 数据结构、持久化、分布式锁、缓存一致性 | 能讲出生产场景 | 高 |
| Netty | NIO、EventLoop、Pipeline、ByteBuf、粘包拆包 | 源码级 | 中高 |
如果时间有限,先保证 MySQL、Redis、JVM 三块能应对 30 分钟以上的深度追问,再补 Spring 源码,最后把 Netty 作为高并发架构的加分项。
1.3 最新热词要不要追:从 Spring AI 说起
搜索热词给了很多信号,比如spring ai、spring ai alibaba。这些新方向确实会出现在 2026 秋招的话题里,但不要本末倒置。
框架热点的价值不在“面试直接问某段代码”,而在于能看出你是否具备迁移能力。比如 Spring AI 的核心设计,本质上还是通过 Spring 的容器能力管理模型客户端、模板和上下文。如果 IoC、Bean 生命周期不熟,追新框架只能停留在“用过”层面。反之,把 Spring 基础源码吃透,新的 Spring 项目即使没接触过,也能通过官方文档快速上手。
复习时要建立自己的判断:热词用来扩大视野,基础链路用来建立深度。
2. Spring 核心:三级缓存与 Bean 生命周期不能只背结论
2.1 三级缓存解决什么问题
很多 Java 面试题都喜欢问“Spring 如何解决循环依赖”。先看一个最小的问题场景:
@Service public class AService { @Autowired private BService bService; } @Service public class BService { @Autowired private AService aService; }如果 Spring 正在创建 AService,发现需要注入 BService,于是去创建 BService。BService 又反过来依赖 AService,但 AService 还没有完全创建好。这时如果没有任何缓存机制,就会进入无限循环。
Spring 用三级缓存处理单例 Bean 的这种循环依赖。三级缓存是三个 Map:
| 缓存名称 | 存储内容 | 作用 |
|---|---|---|
singletonObjects | 完全创建好的单例 Bean | 对外提供对象 |
earlySingletonObjects | 已实例化但尚未完成属性填充的早期对象 | 缓存提前暴露的对象 |
singletonFactories | 存放ObjectFactory | 延迟生成早期对象或代理对象 |
面试时先说清楚:一级缓存放完整的 Bean,二级缓存放早期的 Bean,三级缓存放能生成对象的工厂。当 BService 需要注入 AService 时,Spring 会从三级缓存中找到 AService 的ObjectFactory,调用它得到一个 AService 的早期引用,放入二级缓存,再注入给 BService。
2.2 从源码视角回答“为什么不能只有二级缓存”
这是面试最容易卡住的地方。很多人能背出三级缓存的名字,但答不出设计原因。
关键在 AOP。Spring 创建 Bean 时,如果这个 Bean 需要生成代理对象,代理的生成时机应该是在 Bean 初始化之后,由BeanPostProcessor的后置处理器处理。可如果 AService 被 BService 提前引用了,此时还没走到代理生成阶段,BService 拿到的应该是什么?
如果只有一级缓存,BService 拿不到 AService,因为 AService 还没创建完。
如果只有二级缓存,Spring 在doCreateBean时就需要立刻创建最终对象放入二级缓存。但此时 AOP 后置处理器还没执行,最终代理对象还没生成,提前放进去的普通对象就无法被后续代理替换。为了解决这个问题,三级缓存存的是ObjectFactory,直到有别的 Bean 真正引用它时,才调用getEarlyBeanReference去生成早期对象。如果 Bean 需要 AOP,这里就能提前生成代理对象;如果不需要,就返回原始实例。
从一个可以手动实现的最小接口看:
@FunctionalInterface public interface ObjectFactory<T> { T getObject(); }Spring 容器在创建 Bean 的过程中,看到这个 Bean 允许提前暴露引用,就会提前放入一个ObjectFactory。真正需要注入时,才调用getObject()得到对象。
还需要注意一个常见坑:三级缓存解决的是单例 Bean 的 setter 注入循环依赖。如果两个 Bean 都通过构造器互相依赖,Spring 在实例化阶段就无法创建对象,三级缓存也救不了。生产环境遇到构造器循环依赖时,常见的处理方式是加@Lazy打断依赖,或者重新设计对象关系。
2.3 “手写 Spring”和 Spring AI 怎么准备
“手写 Spring”是复习 IoC 和 AOP 的高效方法,不需要真的把框架写完整,只要实现一个可运行的迷你容器即可。要覆盖的核心链路包括:
- 扫描指定包下的
@Component。 - 解析
@Autowired依赖。 - 维护单例池。
- 处理循环依赖。
- 用动态代理实现简单 AOP。
当你能在注释里说清“这个步骤对应 Spring 源码里的哪段逻辑”,Spring 源码这块基本就过关了。
对于 Spring AI,建议先理解 Spring 如何把外部模型封装为可替换的客户端。实际面试中,比起背诵某个 AI 接口,更重要的是说明白“模型厂商变化时,你的业务代码如何保持不变”。这个答案背后仍然是 Spring 的配置管理、自动装配和抽象能力。
3. JVM:内存模型、参数调优和 OOM 排查要形成一条完整链路
3.1 JDK、JRE、JVM 概念题与内存区域的回答模板
因为热词里有jdk和jvm、jre的区别、jre和jvm之间的关系,这种基础题看似简单,却能筛掉一批没建立体系的人。
准确表述是:JDK 是 Java 开发工具包,除了包含 JRE,还包含编译器、调试器等工具;JRE 是 Java 运行时环境,包含 JVM 和 Java 类库;JVM 是 Java 虚拟机,负责执行字节码,是整个平台的运行时核心。
JVM 内存区域的考察更深入一些。可以按线程是否共享来分:
| 区域 | 是否线程共享 | 主要作用 |
|---|---|---|
| 程序计数器 | 私有 | 记录当前线程执行的字节码行号 |
| 虚拟机栈 | 私有 | 保存栈帧,包括局部变量、操作数栈、方法返回地址 |
| 本地方法栈 | 私有 | 服务于 native 方法 |
| Java 堆 | 共享 | 存放对象实例、数组 |
| 方法区/元空间 | 共享 | 存放类型信息、常量、静态变量、JIT 编译产物 |
面试被问到“一个 Java 对象创建的过程”时,参考链路是:类加载检查、分配内存、初始化零值、设置对象头、执行构造方法。能把这个链路讲出来,内存模型、对象布局、并发安全这几个点就都带出来了。
3.2 常用 JVM 参数与 G1 调优
热词里有jvm参数 -xx:compilethreshold,说明这类参数题也是关注点。JVM 参数不要死记,要理解它影响哪块内存、什么时候生效、调错的后果。
| 参数 | 含义 | 典型场景 |
|---|---|---|
-Xms | 初始堆大小 | 启动时预分配,避免运行时频繁扩容 |
-Xmx | 最大堆大小 | 应用内存上限 |
-Xss | 单线程栈大小 | 递归深度不足时调大,但不宜过大 |
-XX:MaxMetaspaceSize | 元空间上限 | 限制类元数据占用 |
-XX:+UseG1GC | 使用 G1 收集器 | 面向服务端的多核大堆场景 |
-XX:MaxGCPauseMillis | G1 目标停顿时间 | 调优 G1 时设置的软目标 |
-XX:CompileThreshold | 方法触发 JIT 编译的调用次数 | 控制热点方法编译门槛 |
-XX:CompileThreshold默认值在不同模式下不一样,客户端编译器大约 1500,服务端编译器大约 10000。把它放到 JIT 编译语境里去回答,比单纯报一个数字更有说服力。
G1 收集器是校招和社招都很高频的考点。核心是:G1 将堆划分成多个 Region,通过跟踪每个 Region 的回收价值,优先回收垃圾最多的 Region,让停顿时间尽量可控。面试表达可以是:
“G1 不再像 CMS 那样严格区分年轻代和老年代物理区域,而是把堆分成多个 Region。新生代、老年代都是 Region 的逻辑集合。这样回收时不需要全堆扫描,而是维护一个优先级列表,优先回收收益高的 Region,达到可预测停顿的目标。”
3.3 OOM 与 JVM 参数启动报错的排查路径
热词里有两条非常具体:java: outofmemoryerror: insufficient memory和[error] could not get jvm parameters and dynamic configurations properly。
第一类问题意味着 Java 进程无法获得足够的内存分配。出现时要先确认:
-Xmx设置是否大于物理内存。- 操作系统或容器是否有内存限制。
- 当前进程是否已经存在大量线程,占满了系统内存。
- 32 位 JVM 是否达到地址空间上限。
排查命令可以按顺序执行:
jps -l jstat -gcutil <pid> 1000 jmap -dump:format=b,file=oom.hprof <pid> jstack <pid>拿到堆转储文件后,再用 MAT 等工具分析大对象和引用链。
第二类could not get jvm parameters and dynamic configurations properly的日志,常见于使用应用启动器或动态配置平台时。它不一定代表 JVM 本身崩溃,可能是启动器读取参数失败。排查顺序如下:
| 现象 | 可能原因 | 处理建议 |
|---|---|---|
| 启动器提示无法获取 JVM 参数 | 参数路径或配置中心地址错误 | 检查启动器配置 |
| 动态配置读取为空 | 环境变量未生效 | 检查环境变量和配置文件 |
| 参数包含非法字符 | 堆内存参数写错单位 | 检查-Xmx1024m之类写法 |
| 权限不足 | 运行用户无权读取配置 | 检查目录和文件权限 |
不要一上来就调大堆内存,先确定日志来自哪一层,否则很可能掩盖真正的配置问题。
4. MySQL:从安装到 SQL 优化,再到大事务和存储过程
4.1 安装、Workbench 连接与本地验证
搜索热词里有大量mysql安装教程、mysql workbench使用教程,说明很多同学卡在第一公里。本地环境不稳定,后续索引和事务实验都做不下去。
Windows 环境的推荐流程是:下载 MySQL 安装包,选择 Server 和 Workbench,初始化数据目录,启动服务后用客户端连接。命令行方式简化如下:
mysqld --initialize-insecure net start mysql mysql -uroot -p安装后至少要完成三件事:
- 能用
mysql -uroot -p连接本地实例。 - 能在 Workbench 中新建连接并执行 SQL。
- 能查看
SHOW VARIABLES LIKE 'port';确认端口。
常见连接问题如下:
| 问题现象 | 常见原因 | 处理方式 |
|---|---|---|
| Can't connect to MySQL server | 服务未启动 | net start mysql或检查服务管理 |
| Access denied for user | 密码错误或 root 权限限制 | 重置密码或确认 host 授权 |
| Port 3306 already in use | 端口被占用 | `netstat -ano |
| Workbench 连接超时 | 未放行端口或网络不通 | 检查防火墙、连接地址和端口 |
建议直接把本机 MySQL 当成日常练习环境,每个索引和事务例子都真实执行一遍。面试时能随口说出“我复现过锁等待现象”,比只背理论强很多。
4.2 索引失效与 UPDATE 语法中容易被忽略的锁
热词中mysql中int+5是一个经典索引失效场景。看下面两条 SQL:
SELECT * FROM user WHERE age + 5 = 30; SELECT * FROM user WHERE age = 30 - 5;第一句对索引列做了计算,MySQL 无法直接使用age索引,可能退化为全表扫描。第二句是等值条件,右侧常数可以先计算,因此可以走索引。面试回答时,把“对索引列做运算会导致 B+ Tree 有序性失效”这个原理讲清楚,比背十个索引失效规则更有效。
mysql update语法也是高频搜索点。单表更新最基础的形式是:
UPDATE order SET status = 1 WHERE order_no = 'xxx';但实际工程里要注意两点:第一,WHERE条件必须能有效使用索引,否则UPDATE需要扫描并锁住更多行;第二,大表的批量更新不要一条 SQL 更新全表,否则会产生长事务,占用大量行锁和 undo 日志。
一个相对稳妥的做法是分批更新:
UPDATE order SET status = 2 WHERE id > ? AND id <= ? AND status = 1;每次更新固定行数,循环执行直到没有新的更新行。生产环境还需要结合主从延迟、业务低峰期和监控来设计。
4.3 EXPLAIN 与存储过程
说到 SQL 调优,EXPLAIN是必考工具。
EXPLAIN SELECT * FROM order WHERE user_id = 1001 AND status = 1;观察几个关键列:
type:访问类型,从const到eq_ref到ref到range到index再到all,性能依次变差。key:实际使用的索引。rows:预估扫描行数。Extra:如果出现Using filesort或Using temporary,通常需要优化。
能正确解释这四个字段,SQL 优化就不再是死记硬背。
存储过程在热词中出现频率很高,原因可能是很多培训班项目或老系统会用到。先看一个最小示例:
DELIMITER // CREATE PROCEDURE get_user(IN uid INT) BEGIN SELECT * FROM user WHERE id = uid; END // DELIMITER ; CALL get_user(1);面试被问到存储过程时,不要只说“会用”。更好的表达是:
“存储过程适合业务逻辑固定、对网络往返敏感、数据库团队可控的少量场景。但现代大型业务更倾向于把核心逻辑放在应用层,因为存储过程难以测试、难以做版本管理、扩容成本高,也容易把大量计算压到数据库端。”
这个回答既展示了你会写,也展示了工程判断。
5. Redis:从安装主从到分布式锁,不能只会 setnx
5.1 本地安装、Docker 主从和桌面客户端
Redis 的本地安装和 MySQL 类似,最重要的是能快速启动一个实例。Windows 下可以使用官方提供的 Redis 安装包,也可以使用 Docker 启动:
docker run -d --name redis-single -p 6379:6379 redis:7热词里有docker安装redis主从,说明主从集群也是常见考点。用 Docker Compose 起一主一从的示例:
services: redis-master: image: redis:7 ports: - "6379:6379" command: ["redis-server", "--appendonly", "yes"] redis-slave: image: redis:7 ports: - "6380:6379" command: ["redis-server", "--replicaof", "redis-master", "6379"] depends_on: - redis-master启动后进入从节点验证:
docker exec -it redis-slave redis-cli info replication关注输出中的role:slave和master_link_status:up。理解主从同步时,至少要能说清楚 RDB 快照同步和命令传播的区别。
图形客户端方面,Redis Desktop Manager 一类工具可以帮助查看 key 和 TTL,但不要把图形客户端当成能力。面试更多是命令行操作和原理问题。
5.2 分布式锁的安全写法与 Redisson 续期
分布式锁是 Redis 最高频的面试题。最基础的方案是 setnx 加过期时间:
SET order:pay:1001 uuid-123 EX 10 NX这行命令能同时保证“不存在才设置”和“过期时间”。只看这一句还不够,释放锁时要保证“只有持有者才能删除”:
if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end释放锁必须用 Lua 脚本保证读取和删除的原子性,否则可能出现:线程 A 的锁已经过期,线程 B 拿到了新锁,A 执行DEL把 B 的锁删掉。
如果使用 Java,推荐通过 Redisson 的RLock实现:
RLock lock = redissonClient.getLock("order:pay:" + orderId); try { if (lock.tryLock(3, 30, TimeUnit.SECONDS)) { // 执行业务逻辑 } } finally { if (lock.isHeldByCurrentThread()) { lock.unlock(); } }Redisson 还提供了看门狗机制:如果锁设置了过期时间但没有显式指定 leaseTime,看门狗会定期续期,避免业务还没执行完锁就过期。
面试可以给出对比表:
| 方案 | 优势 | 问题 | 适用场景 |
|---|---|---|---|
SET NX EX | 简单,适合单机 Redis | 释放锁有风险,无续期 | 低并发、可接受短暂失效 |
| Lua 脚本释放锁 | 保证释放原子性 | 仍无自动续期 | 大多数业务锁 |
| Redisson RLock | 可重入,支持续期 | 依赖客户端 SDK | 微服务高并发场景 |
| RedLock | 试图解决主从切换锁丢失 | 实现复杂,争议较大 | 对一致性要求极高的场景 |
回答时最后落到“锁不是银弹,还要结合业务幂等和数据库唯一约束来兜底”,会让面试官觉得你想过完整链路。
5.3 缓存一致性基础
Redis 面试离不开缓存和数据库的一致性问题。最常被接受的方案是 Cache Aside Pattern:
public void updateOrder(Order order) { orderMapper.update(order); redisTemplate.delete("order:" + order.getId()); }核心思想是“更新数据库后删除缓存”,而不是“更新缓存”。下次读取时再回填。延时双删、消息队列异步删除都是在这个基础上的优化。
面试表达建议:先删缓存再更新数据库可能导致脏数据;先更新数据库再删缓存也有极小概率出现并发问题,所以生产环境还要配合缓存过期时间兜底。没有绝对一致,只有“对最终一致性的容忍度”和“补偿手段”。
6. Netty:高并发架构必须掌握的网络编程底座
6.1 从 BIO 到 NIO 再到 Netty
Netty 在很多 Java 招聘需求里写着“加分项”,但在高并发架构面试中越来越常出现。原因很简单:RPC、网关、IM、消息推送,底层都离不开高性能网络通信。
先梳理三种 IO 模型的差异:
| 模型 | 工作方式 | 问题 | 典型场景 |
|---|---|---|---|
| BIO | 每个连接一个线程,阻塞等待数据 | 线程数膨胀,上下文切换严重 | 小型传统项目 |
| NIO | 单线程或少量线程通过 Selector 管理多路连接 | 原生 API 复杂,容易踩坑 | 高性能通信中间件 |
| Netty | 封装 NIO,提供线程模型、编解码、内存池 | 需要理解 EventLoop 和 Pipeline | RPC、网关、IM、推送 |
面试可以先给一句话结论:BIO 是“一连接一线程”,NIO 是“一个线程管多个连接”,Netty 是在 NIO 基础上解决工程化问题的网络框架。
6.2 EventLoop、Pipeline 和线程模型
Netty 的核心组件可以简化成一张地图:
EventLoopGroup:线程池,bossGroup 负责接受连接,workerGroup 负责处理 IO。EventLoop:每个线程绑定一个 Selector,循环处理 IO 事件。ChannelPipeline:责任链,数据进出会依次经过多个 Handler。ByteBuf:Netty 的字节容器,使用引用计数管理内存。ChannelHandler:业务逻辑的载体。
一个最简服务端示例:
EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) { ch.pipeline().addLast(new StringDecoder()); ch.pipeline().addLast(new SimpleChannelInboundHandler<String>() { @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) { ctx.writeAndFlush("receive:" + msg); } }); } }); ChannelFuture f = b.bind(8080).sync(); f.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); }这段代码覆盖了 Netty 面试八成的基础知识。能被问到的问题包括:bossGroup 和 workerGroup 各自职责是什么,默认线程数是多少,为什么业务 Handler 不能执行耗时操作。
默认线程数通常是CPU * 2。如果 Handler 里出现数据库查询、远程调用等耗时操作,会占用 EventLoop 线程,阻塞同线程上其他连接的读写。生产环境应该把耗时任务提交到单独的业务线程池。
常见的坑还有 ByteBuf 和引用计数。使用SimpleChannelInboundHandler时,框架会在处理完后自动释放消息;如果绕过它直接使用ChannelInboundHandlerAdapter,就要注意ReferenceCountUtil.release(msg)或ctx.fireChannelRead(msg),否则可能出现内存泄漏。
6.3 “Netty 为什么快”的源码视角
Netty 性能优势的答案可以从五个点展开:
- NIO 多路复用:一个 EventLoop 能管理大量连接,减少线程数。
- 零拷贝:
CompositeByteBuf、FileRegion等机制减少内存复制。 - 内存池:默认使用池化的
ByteBuf,避免频繁 GC。 - 无锁串行:一个 Channel 的操作基本串行执行,减少锁竞争。
- Pipeline 责任链:把编码、解码、业务处理拆成可插拔模块,系统结构清晰。
这个部分可以关联到高并发架构:网关项目用 Netty 接收海量请求,每个请求经过解码、分发、转发到业务服务,再通过 Promise 或回调返回,这就是一条完整的架构链路。再往后还可以聊粘包拆包、心跳机制、流量控制,这些是 Netty 面试的常见延伸。
7. 从八股到架构实战:面试答题的四层模型和复习清单
7.1 四层答题模型:原理、代码、调优、扩展
同一个知识点,新手回答一句话,高手能拆成四层。以 Redis 分布式锁为例:
第一层,原理。锁的本质是占一个标记,setnx 保证只有一个线程能设置成功;过期时间防止进程崩溃后死锁。
第二层,代码。完整释放锁要使用 Lua 脚本;Java 项目可以直接用 Redisson 的RLock。
第三层,调优。锁粒度不能过大,比如不要锁整个用户缓存,而锁order:pay:{orderId};等待时间、过期时间、续期策略都要根据业务耗时设计。
第四层,扩展。主从切换时锁可能丢失,因此需要评估 RedLock,或者在业务层加幂等判断;分布式锁失败时可以降级到本地限流或数据库唯一约束。
用这个模型去复习,任何考点都能变成一个有深度的面试回答。建议准备一个电子表格,把每个高频知识点填上“原理、代码、调优、扩展”四列。
7.2 30 天复习计划表
秋招准备不必拉太长战线,但一定要有阶段目标。30 天内可以用下面的节奏:
| 阶段 | 时间 | 重点 | 自测方式 |
|---|---|---|---|
| 基础重建 | 第 1-10 天 | Java 基础、JVM、MySQL 索引与事务 | 读八股后自己画图复述 |
| 框架源码 | 第 11-18 天 | Spring IoC、AOP、三级缓存 | 手写迷你容器 |
| 中间件实战 | 第 19-25 天 | Redis 分布式锁、缓存一致性、Netty 线程模型 | 本地 Docker 起一主一从做实验 |
| 面试模拟 | 第 26-30 天 | 项目复盘、高频题、手撕代码 | 录制自己答题,按四层模型打分 |
每天固定 3 小时比周末猛学 10 小时更有效。第 1 天和第 30 天对同一道题的答案深度,应该能明显看到差异,这才算是真正的复习。
7.3 面试前一天检查清单
上考场前,可以按下面的清单快速核对:
- 是否能说出 JDK、JRE、JVM 的关系。
- 是否能画出 JVM 内存区域图。
- 是否能解释 Spring 三级缓存的设计原因。
- 是否能写出
EXPLAIN的关键列。 - 是否能完整写出 Redis 分布式锁的 setnx 和 Lua 释放脚本。
- 是否能画出 Netty 的 EventLoop 和 Pipeline 结构。
- 是否有一个能讲满 5 分钟的“调优或排错”项目故事。
- 是否提前做好了自我介绍,并把介绍中的每个技术点都准备过追问。
清单不要追求多,每一条都要能对应到真实的技术细节。
8. 2026 秋招的节奏与长期积累建议
8.1 秋招节奏:提前批、正式批、补录怎么安排
2026 秋招通常会有提前批、正式批和补录阶段。提前批往往启动早、流程快,适合已经完成一轮复习的人;正式批岗位最多,是绝大多数人的主战场;补录阶段更看重岗位匹配度,适合查漏补缺。
建议准备一张自己的求职记录表,包含公司、岗位、投递时间、笔试平台、面试状态、复盘记录。每一场面试结束后,立刻记录被问到的题目和当时的卡点。很多同学不是能力不够,而是复盘不彻底,同一个问题换家公司照样卡住。
投递策略上,不要只投大厂。Java 生态岗位分布很广,中间件、金融、电商、游戏、企业服务,每一种业务的面试侧重点都不同。广投不等于海投,而是有意识地覆盖不同业务场景,通过面试反馈修正复习方向。
8.2 建立自己的知识点“源码地图”
长期积累的关键是建一份属于自己的知识库。目录可以按技术线组织:
knowledge-base/ spring/ ioc.md aop.md circular-dependency.md jvm/ memory.md gc.md oom.md mysql/ explain.md index-failure.md stored-procedure.md redis/ distributed-lock.md cache-aside.md netty/ thread-model.md bytebuf.md每个文件不需要写成长篇大论,记录三个东西就够了:核心结论、源码位置或日志关键字、可复现的小实验。比如在distributed-lock.md里写:
- 核心结论:setnx 加 expire,释放锁用 Lua。
- 源码位置:Redisson
RLock实现。 - 小实验:用 Redis 客户端模拟锁过期和误删。
这套方法也能反过来用于写技术博客。当你发现自己能用清楚的结构把一个问题写给别人看时,这个知识点就已经不是八股文了。
真正拉开差距的不是背了多少题,而是能在新的项目、新的框架出现时,快速定位它对应的是哪条基础链路。把 Spring、JVM、MySQL、Redis、Netty 这五条线整理成自己的面试知识地图,2026 秋招准备就会从背诵模式进入答题模式。