26年2月京东 Java开发工程师 二面
1. Spring Boot启动时,SpringApplication.run()背后经历了哪几个关键步骤?
思路
按启动全流程:准备环境 → 创建上下文 → 刷新容器 → 加载自动配置 → 初始化Bean → 启动完成
回答示例
面试官您好,run方法的核心步骤是这样的:
首先启动计时器,初始化监听器;然后准备运行环境,加载配置文件、激活配置;接着创建Spring应用上下文;再刷新上下文,扫描Bean、加载自动配置类;然后完成Bean的创建、依赖注入、初始化;最后执行Runner,发布启动完成事件,整个项目就启动好了。
2. MySQL的二阶段提交(2PC)如何解决redo log和binlog的一致性问题?
思路
redo log负责崩溃恢复,binlog负责主从同步,2PC保证两者要么都提交,要么都回滚
回答示例
面试官您好,MySQL通过两阶段提交保证redo和binlog一致。
第一阶段InnoDB写入redo log并标记为prepare;第二阶段MySQL写入binlog,完成后再把redo标记为commit。
如果崩溃在prepare,事务回滚;如果崩溃在写完binlog之后,就提交。
这样就能保证redo和binlog永远一致,不会出现主从数据不一致的问题。
3. 一个三层B+树结构,假设每页存储1000个键值,最多能存储多少行数据?
思路
根节点1页 → 二层1000页 → 三层1000*1000页,叶子存数据
回答示例
面试官您好,三层B+树就是根、非叶子、叶子。
根节点1页,指向1000个子节点;每个子节点再指向1000个叶子节点。
叶子节点总数是1000×1000=100万页。
每页存1000行,所以总共能存 10亿行 数据。
4. JVM中哪些区域可能产生OOM?分别对应什么现象?
思路
堆、元空间、虚拟机栈、直接内存四个区域,分别说明OOM表现
回答示例
面试官您好,四个区域会OOM:
第一,堆OOM,就是对象太多回收不了,报错Java heap space;
第二,元空间OOM,动态类太多,报错Metaspace;
第三,栈OOM,递归太深或线程太多,StackOverflow或无法创建线程;
第四,直接内存OOM,NIO用多了,报错Direct buffer memory。
5. Netty的Reactor线程模型有哪几种类型?主从Reactor如何分工?
思路
单Reactor、多Reactor、主从多Reactor;主Reactor负责连接,从Reactor负责读写
回答示例
面试官您好,三种:单Reactor、多Reactor、主从多Reactor。
主从模式里,主Reactor只处理accept连接,接收到连接后分给从Reactor。
从Reactor负责读写、编解码、业务处理,真正实现高并发。
6. 为什么实际项目不直接用NIO而选择Netty?列举三个具体痛点。
思路
原生NIO太难用,空轮询、粘包拆包、API复杂
回答示例
面试官您好,三个最痛的点:
第一,原生NIO有臭名昭著的空轮询BUG,CPU会跑满;
第二,没有封装好的粘包拆包解决方案,要自己写;
第三,API太复杂,Selector、Channel、Buffer很难维护。
Netty全部帮我们解决了,所以项目都用Netty。
7. Redis内存爆满时,排查和优化的完整路径是什么?
思路
看内存使用 → 看大Key → 看过期Key → 清理、内存淘汰、集群扩容
回答示例
面试官您好,第一步用info memory看内存占用;第二步用bigkeys找大Key;第三步看过期Key是否失效;第四步清理无用数据;第五步配置内存淘汰策略;最后不行就集群扩容、分片存储。
8. 用Redis实现分布式锁时,如何避免死锁?看门狗机制原理是什么?
思路
锁必须加过期时间;Redisson看门狗自动续期
回答示例
面试官您好,避免死锁一定要给锁加过期时间。
看门狗就是Redisson的自动续期机制,只要线程没执行完,就每隔10秒给锁延长30秒,保证业务没完成不会被释放,执行完自动解锁,不会死锁。
9. RabbitMQ如何保证消息不丢失?请从生产端、Broker、消费端三方面说明。
思路
生产端确认、队列持久化、消息持久化、消费端手动ACK
回答示例
面试官您好,生产端用confirm机制确保消息到达交换机;
Broker端要做队列持久化、消息持久化;
消费端必须用手动ACK,处理完再确认,异常就重回队列。
三段都做好,消息就绝对不会丢。
10. MySQL慢查询优化中,如何确认是否命中索引?explain看哪些关键字段?
思路
看type、key、rows、Extra四个关键字段
回答示例
面试官您好,主要看这几个:
type字段,range、ref、const才算命中;
key字段,显示索引名就是用到了;
rows越小越好;
Extra不要出现Using filesort、Using temporary。
这样就能判断索引是否有效。
11. 如何用Redis+MySQL实现30分钟未支付订单自动取消?
思路
Redis过期Key监听 + 定时任务 + 消息队列
回答示例
面试官您好,创建订单时往Redis写一个30分钟过期的Key;
Redis的Key过期事件触发后,去检查订单状态;
如果还是未支付,就修改订单为取消,回滚库存。
也可以用定时任务兜底,保证不会漏单。
12. 设计抽奖系统时,如何保证10万人同时抽奖的概率绝对公平?
思路
提前生成奖品池、Redis Lua原子扣减、随机算法公平
回答示例
面试官您好,首先把奖品提前放到奖品池里;
然后用Redis Lua脚本做原子扣减,保证不超发;
抽奖用统一随机数生成器,所有人概率一致;
绝对不能在业务里判断概率,否则并发下会不公平。
13. 项目中遇到过Full GC频繁吗?如何用MAT分析内存泄漏?
思路
导出dump → 看大对象 → 看GC Roots → 找强引用链
回答示例
面试官您好,遇到过。
首先导出堆dump;
然后用MAT打开,看Histogram找大对象;
再用Path to GC Roots排除弱引用;
最后找到强引用链,定位是哪个集合、哪个静态变量持有对象没释放,就能解决泄漏。
14. ThreadLocal在项目中的应用场景?可能引发什么问题?
思路
存用户信息、事务上下文;内存泄漏、线程复用污染
回答示例
面试官您好,常用在存储登录用户信息、数据库会话、请求上下文。
最大的问题是线程池里线程复用,会导致数据污染;
另外不remove会引发内存泄漏。
所以用完必须调用remove()。
15. 线上CPU突然100%,你的排查命令链是什么?
思路
top → top -Hp → printf → jstack → 找业务代码
回答示例
面试官您好,命令链是固定的:
先用top找到CPU高的进程;
再top -Hp找到高耗CPU线程;
printf转16进制;
jstack导出栈;
最后找到对应业务代码,定位死循环、GC频繁或计算密集逻辑。
查看1道真题和解析