一、JVM:面試中的 “基礎門檻”
JVM 是 Java 跨平台特性的核心,也是面試中最易拉開差距的模塊。面試官不僅會考察理論知識,更會結合 “內存溢出排查”“性能優化” 等實際場景提問。
1.1 核心考點:JVM 內存模型(JDK 8+)
JDK 8 取消了永久代,引入元空間(Metaspace),內存模型主要分為以下區域,需重點區分 “線程私有” 與 “線程共享”:
- 線程私有區域(隨線程創建 / 銷燬):
- 程序計數器:記錄當前線程執行字節碼的行號,唯一不會 OOM 的區域;
- 虛擬機棧:存儲方法調用的棧幀(局部變量表、操作數棧等),棧深度不足會拋StackOverflowError,內存不足會拋OutOfMemoryError;
- 本地方法棧:與虛擬機棧類似,為 Native 方法服務。
- 線程共享區域(整個 JVM 進程共享):
- 堆(Heap):存儲對象實例,垃圾回收(GC)的核心區域,分為年輕代(Eden + Survivor)和老年代;
- 元空間(Metaspace):存儲類元信息(類結構、方法信息等),默認使用本地內存,避免了永久代 OOM 問題。
面試高頻問題:“JDK 8 為什麼取消永久代,改用元空間?”
參考回答:① 永久代大小難確定,容易因類加載過多導致 OOM;② 元空間使用本地內存,可動態擴展,減少內存溢出風險;③ 便於 HotSpot 與其他 JVM(如 JRockit)融合。
1.2 垃圾回收(GC):從 “理論” 到 “實戰”
GC 是 JVM 面試的重中之重,需掌握 “回收算法”“垃圾收集器”“GC 日誌分析” 三大模塊。
(1)垃圾判定算法
- 引用計數法:通過對象引用數判斷是否可回收,無法解決循環引用問題(如 A 引用 B,B 引用 A);
- 可達性分析:以 “GC Roots”(如虛擬機棧引用的對象、靜態變量引用的對象)為起點,遍歷對象引用鏈,不可達的對象標記為可回收。
(2)常見垃圾收集器(JDK 8 + 主流)
需明確不同收集器的適用場景,避免死記硬背:
|
收集器 |
適用區域 |
特點 |
適用場景 |
|
Serial |
年輕代 |
單線程回收,暫停時間長 |
客户端應用、小型程序 |
|
Parallel Scavenge |
年輕代 |
多線程回收,追求高吞吐量 |
服務器端批量處理任務 |
|
CMS(Concurrent Mark Sweep) |
老年代 |
併發回收,低暫停時間 |
互聯網應用(如 Web 服務) |
|
G1(Garbage-First) |
整堆 |
分區回收,兼顧吞吐量與低延遲 |
大內存場景(如 16G + 堆內存) |
面試高頻問題:“CMS 收集器的工作流程,以及可能出現的問題?”
參考回答:流程分為 4 步:① 初始標記(STW,標記 GC Roots 直接引用的對象);② 併發標記(與用户線程並行,遍歷引用鏈);③ 重新標記(STW,修正併發標記的偏差);④ 併發清除(與用户線程並行,回收垃圾)。
可能問題:① 併發清除階段產生 “浮動垃圾”(新生成的垃圾無法回收);② 內存碎片(標記 - 清除算法導致,需通過 “CMS Full GC” 整理碎片,暫停時間長)。
(3)GC 實戰:內存溢出排查
面試官常問 “如何排查 OOM 問題”,需掌握工具與流程:
- 開啓 JVM 參數:添加-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./heapdump.hprof,OOM 時自動生成堆轉儲文件;
- 分析工具:使用 JDK 自帶的jhat或可視化工具(如 MAT、VisualVM),查看對象引用鏈,定位內存泄漏點(如靜態集合未清理、線程池核心線程持有大對象);
- 常見場景:① ArrayList 無限添加元素導致堆 OOM;② 遞歸調用過深導致棧 OOM;③ 類加載過多(如動態生成類)導致元空間 OOM。
二、集合框架:從 “使用” 到 “原理”
集合框架是 Java 開發的基礎,面試中不僅會考察 API 使用,更會深入底層數據結構與源碼實現(如 HashMap、ConcurrentHashMap)。
2.1 核心集合體系
需明確 Collection 與 Map 兩大接口的繼承關係,避免混淆:
- Collection:存儲單值元素,主要子類包括 List(有序、可重複)、Set(無序、不可重複)、Queue(隊列,FIFO);
- Map:存儲鍵值對(Key-Value),主要實現類包括 HashMap、TreeMap、ConcurrentHashMap。
2.2 高頻考點:HashMap(JDK 8)
HashMap 是面試中 “必問” 知識點,需掌握數據結構、擴容機制、線程安全性三大核心。
(1)底層數據結構
JDK 8 中,HashMap 採用 “數組 + 鏈表 + 紅黑樹” 的結構:
- 數組(哈希桶):存儲鏈表 / 紅黑樹的頭節點,數組長度默認 16(必須是 2 的冪,便於通過(n-1)&hash計算索引);
- 鏈表:當哈希衝突時,元素以鏈表形式存儲,鏈表長度超過 8 且數組長度≥64 時,轉為紅黑樹(提升查詢效率,從 O (n) 到 O (logn));
- 紅黑樹:當鏈表長度小於 6 時,紅黑樹轉回鏈表(避免紅黑樹維護成本過高)。
(2)擴容機制
- 觸發條件:當元素數量(size)超過 “負載因子(默認 0.75)× 數組長度” 時,觸發擴容,數組長度翻倍;
- 擴容核心:重新計算每個元素的哈希索引((newCap -1)&hash),並遷移元素(JDK 8 優化了遷移邏輯,避免重複計算哈希)。
(3)線程安全性
HashMap 線程不安全,併發場景下可能出現 “鏈表環”(JDK 7)或數據覆蓋問題。解決方式:
- 替換為ConcurrentHashMap(JDK 8 使用 CAS+synchronized 實現,效率高於 JDK 7 的分段鎖);
- 使用Collections.synchronizedMap(new HashMap<>())(全局鎖,效率低)。
面試高頻問題:“JDK 7 與 JDK 8 中 HashMap 的區別?”
參考回答:① 數據結構:JDK 7 是 “數組 + 鏈表”,JDK 8 是 “數組 + 鏈表 + 紅黑樹”;② 哈希計算:JDK 7 多次擾動哈希(減少衝突),JDK 8 簡化為 “hashCode ^ (hashCode >>> 16)”;③ 擴容遷移:JDK 7 頭插法(易產生鏈表環),JDK 8 尾插法(避免環);④ 初始化:JDK 7 在構造函數中初始化數組,JDK 8 在第一次 put 時初始化。
三、併發編程:面試中的 “難點與重點”
併發編程是 Java 後端開發的核心能力,面試官會圍繞 “線程池、鎖機制、併發容器” 展開,考察候選人對多線程問題的理解與解決能力。
3.1 線程池:從 “參數” 到 “實戰選型”
線程池是併發編程的 “利器”,也是面試高頻考點,需掌握 “核心參數、工作原理、拒絕策略”。
(1)核心參數(ThreadPoolExecutor)
public ThreadPoolExecutor(
int corePoolSize, // 核心線程數(常駐線程)
int maximumPoolSize, // 最大線程數(核心+臨時線程)
long keepAliveTime, // 臨時線程空閒時間
TimeUnit unit, // 時間單位
BlockingQueue<Runnable> workQueue, // 任務隊列
ThreadFactory threadFactory, // 線程工廠(自定義線程名)
RejectedExecutionHandler handler // 拒絕策略
)
(2)工作原理
- 提交任務時,優先創建核心線程執行;
- 核心線程滿後,任務放入工作隊列;
- 隊列滿後,創建臨時線程執行;
- 臨時線程滿後,觸發拒絕策略。
(3)拒絕策略
需根據業務場景選擇合適的拒絕策略:
- AbortPolicy(默認):直接拋RejectedExecutionException,中斷業務;
- CallerRunsPolicy:由提交任務的線程執行(如主線程),減緩任務提交速度;
- DiscardPolicy:默默丟棄任務,無任何提示;
- DiscardOldestPolicy:丟棄隊列中最舊的任務,嘗試提交新任務。
面試高頻問題:“如何設計線程池的核心參數?”
參考回答:需結合業務類型(CPU 密集型 / IO 密集型)判斷:
- CPU 密集型(如計算任務):核心線程數 = CPU 核心數 + 1(減少線程切換開銷);
- IO 密集型(如數據庫查詢、HTTP 請求):核心線程數 = CPU 核心數 × 2(線程大部分時間在等待 IO,可多創建線程提高利用率);
- 隊列選擇:無界隊列(如 LinkedBlockingQueue)適合任務量穩定場景,避免拒絕;有界隊列(如 ArrayBlockingQueue)適合任務量波動大場景,防止內存溢出。
3.2 鎖機制:從 “synchronized” 到 “Lock”
鎖是解決併發安全的核心,需掌握synchronized與Lock的區別,以及 “樂觀鎖”“悲觀鎖” 的應用場景。
(1)synchronized:從 “重量級鎖” 到 “優化”
JDK 6 對synchronized進行了優化,引入 “偏向鎖、輕量級鎖、重量級鎖” 三級鎖狀態,減少性能開銷:
- 偏向鎖:單線程場景下,避免鎖競爭,直接標記線程 ID;
- 輕量級鎖:多線程交替執行,通過 CAS 嘗試獲取鎖,避免進入內核態;
- 重量級鎖:多線程競爭激烈,通過操作系統互斥量(Mutex)實現,會導致線程阻塞(上下文切換開銷大)。
(2)Lock 接口(ReentrantLock)
ReentrantLock是synchronized的補充,支持更多特性:
- 可中斷鎖:通過lockInterruptibly()中斷等待鎖的線程;
- 可超時鎖:通過tryLock(long time, TimeUnit unit)避免無限等待;
- 公平鎖:通過構造函數new ReentrantLock(true)實現,按線程等待順序獲取鎖(默認非公平鎖,效率更高);
- 條件變量:通過newCondition()實現多線程間的通信(如生產者 - 消費者模型)。
面試高頻問題:“synchronized 與 ReentrantLock 的區別?”
參考回答:① 鎖實現:synchronized 是 JVM 層面的鎖(字節碼指令monitorenter/monitorexit),ReentrantLock 是 Java 層面的鎖(基於 AQS);② 特性:ReentrantLock 支持可中斷、可超時、公平鎖,synchronized 不支持;③ 釋放鎖:synchronized 自動釋放(異常或方法結束),ReentrantLock 需手動釋放(finally中調用unlock());④ 性能:JDK 6 後兩者性能接近,簡單場景用 synchronized,複雜場景用 ReentrantLock。
四、Spring 生態:後端開發的 “基石”
Spring 是 Java 後端開發的主流框架,面試中會圍繞 “Spring IoC、Spring AOP、Spring Boot、Spring Cloud” 展開,考察候選人對框架設計思想與實戰應用的理解。
4.1 Spring IoC:控制反轉與依賴注入
IoC(Inversion of Control)是 Spring 的核心思想,即 “將對象的創建與依賴管理交給 Spring 容器”,避免硬編碼耦合。
(1)依賴注入(DI)的三種方式
- 構造器注入:通過構造函數注入依賴,強制依賴必須傳入(推薦,避免空指針);
- Setter 注入:通過 setter 方法注入依賴,適合可選依賴;
- 字段注入:通過@Autowired直接注入字段,代碼簡潔但不便於測試(不推薦)。
(2)Bean 的作用域與生命週期
- 作用域:默認singleton(單例,整個容器一個實例),其他包括prototype(每次獲取新實例)、request(每個 HTTP 請求一個實例)、session(每個會話一個實例);
- 生命週期:① 實例化(調用構造函數);② 屬性注入(設置依賴);③ 初始化(@PostConstruct或InitializingBean);④ 銷燬(@PreDestroy或DisposableBean)。
面試高頻問題:“Spring Bean 的循環依賴如何解決?”
參考回答:循環依賴指 A 依賴 B,B 依賴 A。Spring 通過 “三級緩存” 解決單例 Bean 的循環依賴:
- 一級緩存:存儲已初始化完成的 Bean;
- 二級緩存:存儲已實例化但未注入依賴的 Bean;
- 三級緩存:存儲 Bean 的工廠對象(用於生成代理對象)。
流程:A 實例化後放入三級緩存,注入 B 時發現 B 未創建,B 實例化後放入三級緩存,注入 A 時從三級緩存獲取 A 的工廠對象,生成 A 的代理對象放入二級緩存,B 初始化完成後放入一級緩存,再回到 A 注入 B,A 初始化完成後放入一級緩存。
注意:prototypeBean 不支持循環依賴(每次獲取新實例,無法緩存),會拋BeanCurrentlyInCreationException。
4.2 Spring AOP:面向切面編程
AOP(Aspect-Oriented Programming)是 Spring 的另一核心,通過 “橫切關注點”(如日誌、事務、權限)的提取,實現代碼解耦。
(1)核心概念
- 切面(Aspect):橫切關注點的封裝(如@Aspect註解的類);
- 通知(Advice):切面的具體邏輯(如@Before、@After、@Around);
- 連接點(JoinPoint):程序執行的某個位置(如方法調用、字段賦值);
- 切入點(Pointcut):篩選連接點的表達式(如execution(* com.xxx.service.*.*(..)));
- 目標對象(Target):被代理的原始對象。
(2)實現原理
Spring AOP 基於動態代理實現,分為兩種方式:
- JDK 動態代理:基於接口,代理類實現目標接口,通過Proxy.newProxyInstance()生成代理對象;
- CGLIB 動態代理:基於類,代理類繼承目標類,通過 ASM 字節碼框架生成代理對象。
規則:如果目標對象實現了接口,默認用 JDK 動態代理;否則用 CGLIB。可通過proxyTargetClass=true強制使用 CGLIB。
面試高頻問題:“Spring 事務的傳播機制有哪些?如何實現的?”
參考回答:事務傳播機制定義了多個事務方法嵌套調用時,事務的行為(如是否新建事務、是否加入現有事務),核心傳播機制包括:
- REQUIRED(默認):如果當前有事務,加入;否則新建事務;
- REQUIRES_NEW:無論當前是否有事務,都新建事務(原有事務掛起);
- SUPPORTS:如果當前有事務,加入;否則以非事務方式執行;
- NOT_SUPPORTED:以非事務方式執行,原有事務掛起;
- NEVER:以非事務方式執行,存在事務則拋異常;
- MANDATORY:必須在事務中執行,無事務則拋異常;
- NESTED:如果當前有事務,在嵌套事務中執行(獨立提交 / 回滾);否則新建事務。
實現原理:Spring 事務基於 AOP,通過TransactionInterceptor攔截目標方法,在方法執行前開啓事務,執行後提交 / 回滾事務(異常時),底層依賴TransactionManager(如DataSourceTransactionManager)與數據庫事務(JDBC 的Connection)。
五、數據庫:從 “SQL 優化” 到 “事務隔離”
數據庫是後端開發的 “數據存儲核心”,面試中會圍繞 “SQL 優化、索引、事務隔離級別、分庫分表” 展開,考察候選人的數據存儲與性能優化能力。
5.1 索引:提升查詢效率的 “關鍵”
索引是數據庫優化的核心,需掌握 “索引類型、索引原理、失效場景”。
(1)索引類型
- 按數據結構:B + 樹索引(InnoDB 默認,適合範圍查詢)、Hash 索引(適合等值查詢,不支持範圍)、全文索引(如 Elasticsearch 中用於文本檢索);
- 按功能:主鍵索引(唯一且非空,InnoDB 中主鍵索引即聚簇索引)、唯一索引(值唯一,允許空)、普通索引(無約束)、聯合索引(多列組合,需遵循 “最左前綴原則”)。
(2)索引原理(InnoDB 聚簇索引)
- InnoDB 中,聚簇索引(主鍵索引)是核心,數據與索引存儲在一起,葉節點存儲完整的行數據;非聚簇索引(如普通索引、唯一索引)的葉節點存儲主鍵值,查詢時需通過主鍵值回表查詢完整數據(即 “回表” 操作)。
示例:若表 user 主鍵為 id,有普通索引 name,執行 select * from user where name = '張三' 時: - 先通過 name 索引找到對應的主鍵值 id=10;
- 再通過 id 聚簇索引找到 id=10 對應的完整行數據。
(3)索引失效場景(面試高頻)
索引失效會導致全表掃描,需重點規避以下場景:
- 使用函數或表達式操作索引列:如 where substring(name, 1, 1) = '張'(可用 where name like '張%' 替代);
- 索引列使用不等於(!=、<>)、not in、is not null:會導致索引失效,轉向全表掃描;
- 字符串未加引號:如 where name = 123(name 為字符串類型,會觸發類型轉換,導致索引失效);
- 聯合索引不滿足最左前綴原則:如聯合索引 (name, age),查詢 where age = 20 會導致索引失效;
- like 以 % 開頭:如 where name like '%三'(無法利用索引,若為 like '張%' 則可利用索引)。
面試高頻問題:“什麼是覆蓋索引?如何避免回表?”
解析:覆蓋索引指查詢的列均可通過索引獲取,無需回表。例如:
- 表 user 有聯合索引 (name, age),執行 select name, age from user where name = '張三' 時,可直接通過聯合索引獲取 name 和 age,無需回表;
- 避免回表的核心是:讓查詢的列包含在索引中(如設計合適的聯合索引),減少 “回表” 帶來的性能開銷。
5.2 SQL 優化:從 “慢查詢” 到 “高效執行”
SQL 優化是數據庫面試的核心,需掌握 “慢查詢分析流程”“優化技巧” 兩大模塊。
(1)慢查詢分析流程
- 開啓慢查詢日誌:在 MySQL 配置文件中添加 slow_query_log = 1(開啓慢查詢)、long_query_time = 1(執行時間超過 1 秒的查詢記錄到日誌)、slow_query_log_file = /var/lib/mysql/slow.log(日誌存儲路徑);
- 分析慢查詢日誌:使用工具 mysqldumpslow(如 mysqldumpslow -s c -t 10 /var/lib/mysql/slow.log,查看執行次數最多的前 10 條慢查詢)或可視化工具(如 Navicat 慢查詢分析);
- 查看執行計劃:通過 explain 分析 SQL 執行計劃,重點關注 type(索引類型)、key(實際使用的索引)、rows(預估掃描行數)、Extra(額外信息,如 “Using index”“Using filesort”)。
- (2)SQL 優化核心技巧
- 優化查詢語句:避免 select *(只查詢需要的列,便於利用覆蓋索引)、拆分複雜查詢(如將多表關聯的大查詢拆分為多個小查詢);
- 優化表結構:合理設計字段類型(如用 int 代替 varchar 存儲 ID、用 datetime 代替 varchar 存儲時間)、避免冗餘字段(通過關聯查詢獲取數據,減少數據不一致風險);
- 優化索引:刪除冗餘索引(如聯合索引 (name, age) 已包含 name 單列索引的功能,無需重複創建 name 索引)、避免過度索引(索引會增加插入 / 更新 / 刪除的開銷);
- 處理分頁查詢:大數據量分頁(如 limit 100000, 10)會導致全表掃描,可通過主鍵過濾優化:
-- 優化前(全表掃描,效率低)
select * from user limit 100000, 10;
-- 優化後(利用主鍵索引,效率高)
select * from user where id > 100000 limit 10;
5.3 事務隔離級別:解決 “併發一致性問題”
數據庫事務需滿足 ACID 特性(原子性、一致性、隔離性、持久性),而隔離性是解決併發場景下 “髒讀、不可重複讀、幻讀” 問題的核心。
(1)併發一致性問題
- 髒讀:一個事務讀取到另一個事務未提交的數據(如事務 A 修改了數據但未提交,事務 B 讀取到該未提交數據,之後事務 A 回滾,事務 B 讀取的數據為 “髒數據”);
- 不可重複讀:同一事務內,多次讀取同一數據,結果不一致(如事務 A 第一次讀取數據為 100,事務 B 修改數據為 200 並提交,事務 A 再次讀取數據為 200);
- 幻讀:同一事務內,多次執行同一查詢,返回的結果集行數不一致(如事務 A 查詢 “age> 20” 的用户有 10 條,事務 B 插入一條 “age=25” 的用户並提交,事務 A 再次查詢 “age > 20” 的用户有 11 條)。
(2)MySQL 事務隔離級別(InnoDB 支持)
MySQL 支持 4 種隔離級別,默認隔離級別為 Repeatable Read(可重複讀),不同級別解決的一致性問題不同:
|
隔離級別 |
髒讀 |
不可重複讀 |
幻讀 |
實現原理 |
|
Read Uncommitted(讀未提交) |
允許 |
允許 |
允許 |
無鎖,直接讀取數據 |
|
Read Committed(讀已提交) |
禁止 |
允許 |
允許 |
行級鎖,讀取已提交的數據 |
|
Repeatable Read(可重複讀) |
禁止 |
禁止 |
禁止 |
行級鎖 + MVCC(多版本併發控制) |
|
Serializable(串行化) |
禁止 |
禁止 |
禁止 |
表級鎖,事務串行執行,性能最低 |
面試高頻問題:“InnoDB 的 Repeatable Read 級別如何解決幻讀?”
參考回答:InnoDB 通過 MVCC(多版本併發控制) 解決幻讀:
- MVCC 為每行數據添加隱藏列(DB_TRX_ID 事務 ID、DB_ROLL_PTR 回滾指針),通過回滾日誌維護數據的多個版本;
- 事務啓動時生成一個 “Read View”(讀視圖),包含當前活躍事務的 ID 列表,查詢時只讀取 “Read View” 之前提交的版本數據;
- 即使其他事務插入新數據並提交,當前事務的 “Read View” 未變化,查詢時仍讀取舊版本數據,從而避免幻讀。
5.4 分庫分表:解決 “大數據量存儲” 問題
當單表數據量超過 1000 萬或單庫數據量超過 100GB 時,會導致查詢緩慢、索引失效,需通過分庫分表拆分數據。
(1)分庫分表方案
- 水平拆分(按行拆分):將同一表的數據按規則拆分到多個表 / 庫中,每個表 / 庫的結構相同。
- 拆分規則:按範圍(如按 id 分,1-10000 存表 1,10001-20000 存表 2)、按哈希(如 id % 4 分 4 個表)、按時間(如按月份分表,user_202401、user_202402);
- 適用場景:單表數據量過大,需分散存儲壓力。
- 垂直拆分(按列拆分):將同一表的不同列拆分到多個表 / 庫中,每個表 / 庫存儲部分列數據。
- 拆分規則:按業務關聯性拆分(如表 user 拆分為 user_base(存儲基本信息:id、name、age)和 user_extend(存儲擴展信息:avatar、address));
- 適用場景:表字段過多,部分字段訪問頻率低(如 avatar 訪問頻率低,拆分後可減少查詢時的數據傳輸量)。
- (2)分庫分表工具
- 客户端工具:Sharding-JDBC(輕量級,基於 JDBC 擴展,嵌入應用中,無需額外部署服務);
- 中間件工具:MyCat(基於 Proxy 模式,獨立部署服務,應用通過 MyCat 訪問數據庫,支持更多高級特性如讀寫分離、容災)。
(3)分庫分表挑戰(面試高頻)
- 分佈式事務:跨庫 / 跨表操作需保證事務一致性,常用方案有 2PC(兩階段提交,如 Seata AT 模式)、TCC(Try-Confirm-Cancel)、SAGA 模式;
- 跨庫查詢:如查詢 “所有表中 age> 20 的用户”,需通過工具聚合多表結果(如 Sharding-JDBC 的聯邦查詢);
- 全局 ID:分庫分表後需保證 ID 唯一,常用方案有 UUID(無序,不利於索引)、雪花算法(Snowflake,生成有序 ID,包含時間戳、機器 ID、序列號)、數據庫自增(如單獨用一個庫的表生成自增 ID)。
面試高頻問題:“分庫分表後,如何實現全局唯一 ID?”
參考回答:推薦使用雪花算法(Snowflake),其結構如下(64 位 Long 類型):
- 1 位符號位:固定為 0(表示正數);
- 41 位時間戳:記錄毫秒級時間(可使用約 69 年);
- 10 位機器 ID:可部署 1024 台機器;
- 12 位序列號:每台機器每秒可生成 4096 個 ID;
雪花算法生成的 ID 有序,便於索引,且無需依賴數據庫,性能高,是分庫分表中全局 ID 的首選方案。
六、面試實戰:從 “知識” 到 “落地”
掌握核心技術後,還需通過實戰演練提升面試表現,以下為高頻場景的應對策略:
6.1 項目經驗梳理:STAR 法則
面試中 “項目經驗” 是重點,需用 STAR 法則清晰表達:
- S(Situation):項目背景(如 “為解決電商平台訂單查詢緩慢問題,需優化訂單系統”);
- T(Task):你的任務(如 “負責訂單表分庫分表設計與實現,以及慢查詢優化”);
- A(Action):具體行動(如 “使用 Sharding-JDBC 按訂單創建時間分表,優化 3 條慢查詢 SQL,添加 2 個聯合索引”);
- R(Result):結果與數據(如 “訂單查詢時間從 500ms 降至 50ms 以內,支持日均 100 萬訂單存儲”)。
6.2 技術問題應對:“原理 + 場景 + 優化”
回答技術問題時,需從 “原理” 到 “實際場景” 再到 “優化方案” 展開,避免只説理論:
- 示例:被問 “HashMap 線程不安全,如何解決?”
- 原理:HashMap 併發時會出現數據覆蓋(如 JDK 8)或鏈表環(JDK 7);
- 場景:若為高併發讀、低併發寫場景,可使用 ConcurrentHashMap;若為單線程或低併發場景,用 HashMap 即可;
- 優化:ConcurrentHashMap JDK 8 用 CAS+synchronized 替代 JDK 7 的分段鎖,性能更高,可優先選擇。
6.3 問題排查:“工具 + 流程 + 結論”
面試官常問 “如何排查線上問題”,需結合工具與流程回答:
- 示例:“線上應用出現內存溢出(OOM),如何排查?”
- 工具:JDK 自帶 jps(查看進程 ID)、jmap(生成堆轉儲文件:jmap -dump:format=b,file=heap.hprof 12345)、MAT(分析堆文件);
- 流程:① 開啓 JVM 參數 -XX:+HeapDumpOnOutOfMemoryError 自動生成堆文件;② 用 MAT 打開堆文件,查看 “Leak Suspects”(內存泄漏疑點);③ 定位大對象引用鏈(如靜態集合未清理);
- 結論:如 “發現緩存工具類中的靜態 Map 未設置過期時間,導致對象堆積,修改為定時清理後 OOM 問題解決”。
七、總結
Java 後端面試核心圍繞 “JVM、集合框架、併發編程、Spring 生態、數據庫” 五大領域,需做到:
- 理解原理:不僅要記住結論,更要掌握底層邏輯(如 HashMap 紅黑樹轉換的條件、Spring 三級緩存解決循環依賴的流程);
- 結合場景:技術需落地到實際場景(如線程池參數設計需區分 CPU 密集型與 IO 密集型);
- 實戰能力:掌握問題排查工具與流程(如 GC 日誌分析、慢查詢優化、OOM 排查);