被问哭了,一位小姐姐的阿里面经!(附部分答案)
這篇文章是一位 女讀者 (加粗!太難得)的面試阿里的經歷分享,雖然第二面就失敗了,但是這樣的經歷對自己幫助應該還是很大的。
下面的一些問題非常具有代表性,部分問題我簡單做了修改(有些問題表述的不那么準確)。這些問題對于大家用于自測或者準備面試都很有幫助。
我只給出了少部分問題的參考答案,因為自己真的抽不出有時間來把每一個問題都細心解答一遍了。單單是回答了下面的少部分問題,就從昨晚 9 點一直忙到 12 點半。
有答案需求的小伙伴,評論區(qū)安排,需要的人多的話,我這周末花時間把一份頂好的參考答案都整出來!
小聲 BB:寫參考答案其實挺費時間的,相比于面試的時候回答問題來說要麻煩很多。很多面試官自己問的問題可能連自己都不清楚,哈哈哈!
自我介紹就不說了,每一面都會讓你說。
項目相關
這個面試前肯定要準備的,Guide 哥的文章中也提到了很多次,我準備的還算充分,面試官比較滿意。
介紹一下你簡歷上寫的項目?自己主要做了什么?(簡歷上雖然寫了,但是面試官還是問了)
你覺得項目里給你最大的挑戰(zhàn)是什么?遇到了什么問題?如何解決的?從中學到了什么?
項目的架構圖能畫一下不?(一個很 low 的后臺網站)
覺得項目有哪些地方可以改進完善?(我說可以加一個 redis 緩存把熱點數據緩存起來)
為什么要用 Nginx?有啥用?優(yōu)缺點?
有沒有遇到過內存泄漏的場景?
Java 基礎
StringBuilder 和 StringBuffer(StringBuffer 是線程安全的,StringBuilder 是不安全的)
如何實現靜態(tài)代理?有啥缺陷?
動態(tài)代理的作用?在哪些地方用到了?(AOP、RPC 框架中都有用到)
JDK 的動態(tài)代理和 CGLIB 有什么區(qū)別?
談談對 Java 注解的理解,解決了什么問題?
Java 反射?反射有什么缺點?你是怎么理解反射的(為什么框架需要反射)?
---第 4 題參考答案---
JDK 動態(tài)代理只能只能代理實現了接口的類,而 CGLIB 可以代理未實現任何接口的類。 另外, CGLIB 動態(tài)代理是通過生成一個被代理類的子類來攔截被代理類的方法調用,因此不能代理聲明為 final 類型的類和方法。就二者的效率來說,大部分情況都是 JDK 動態(tài)代理更優(yōu)秀,隨著 JDK 版本的升級,這個優(yōu)勢更加明顯。
---第 5 題參考答案---
Java 語言中的類、方法、變量、參數和包等都可以注解標記,程序運行期間我們可以獲取到相應的注解以及注解中定義的內容,這樣可以幫助我們做一些事情。比如說 Spring 中如果檢測到說你的類被 @Component注解標記的話,Spring 容器在啟動的時候就會把這個類歸為自己管理,這樣你就可以通過 @Autowired注解注入這個對象了。
---第 6 題參考答案---
反射介紹:
JAVA 反射機制是在運行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態(tài)獲取的信息以及動態(tài)調用對象的方法的功能稱為 java 語言的反射機制。
反射的優(yōu)缺點如下:
優(yōu)點: 運行期類型的判斷,動態(tài)加載類,提高代碼靈活度。
缺點: 1,性能瓶頸:反射相當于一系列解釋操作,通知 JVM 要做的事情,性能比直接的 java 代碼要慢很多。2,安全問題,讓我們可以動態(tài)操作改變類的屬性同時也增加了類的安全隱患。
為什么框架需要反射技術?
在我們平時的項目開發(fā)過程中,基本上很少會直接使用到反射機制,但這不能說明反射機制沒有用,實際上有很多設計、開發(fā)都與反射機制有關,例如模塊化的開發(fā),通過反射去調用對應的字節(jié)碼;動態(tài)代理設計模式也采用了反射機制,還有我們日常使用的 Spring/Hibernate 等框架也大量使用到了反射機制。
舉例:
我們在使用 JDBC 連接數據庫時使用 Class.forName()通過反射加載數據庫的驅動程序;
Spring 框架的 IOC(動態(tài)加載管理 Bean)創(chuàng)建對象以及 AOP(動態(tài)代理)功能都和反射有聯(lián)系;
動態(tài)配置實例的屬性;
......
更多 Java 基礎相關的問題,請參考這篇頂好頂完善的文章:「Java 面試題精華集」Java 基礎知識篇(2020 最新版)附 PDF 版 ! 。
集合框架
HashMap 的底層實現、JDK 1.8 的時候為啥將鏈表轉換成紅黑樹?、HashMap 的負載因子、HashMap 和 Hashtable 的區(qū)別?
有哪些集合是線程不安全的?怎么解決呢?
什么是快速失敗(fail-fast)、能舉個例子嗎?、什么是安全失敗(fail-safe)呢?
集合框架相關的問題的答案,請參考這篇頂好頂完善的文章:「Java 面試題精華集」1w 字的 Java 集合框架篇(2020 最新版)附 PDF 版 ! ,里面介紹的非常詳細非常棒!
多線程
在多線程情況下如何保證線程安全
synchronized 作用,底層實現
ReetrantLock 和 synchronized 的區(qū)別
AQS
線程池作用?Java 線程池有哪些參數?阻塞隊列有幾種?拒絕策略有幾種?
線程死鎖
ThreadLocal 是什么,應用場景是什么,原理是怎樣的
介紹一下 Java 有哪些鎖(synchronized、juc 提供的鎖如 ReentrantLock、CountDownLatch、CyclicBarrier、Semaphore 等)
---第 6 題參考答案---
線程死鎖描述的是這樣一種情況:多個線程同時被阻塞,它們中的一個或者全部都在等待某個資源被釋放。由于線程被無限期地阻塞,因此程序不可能正常終止。
如下圖所示,線程 A 持有資源 2,線程 B 持有資源 1,他們同時都想申請對方的資源,所以這兩個線程就會互相等待而進入死鎖狀態(tài)。
線程死鎖示意圖---第 7 題參考答案---
通常情況下,我們創(chuàng)建的變量是可以被任何一個線程訪問并修改的。如果想實現每一個線程都有自己的專屬本地變量該如何解決呢? JDK 中提供的ThreadLocal類正是為了解決這樣的問題。ThreadLocal類主要解決的就是讓每個線程綁定自己的值,可以將ThreadLocal類形象的比喻成存放數據的盒子,盒子中可以存儲每個線程的私有數據。
如果你創(chuàng)建了一個ThreadLocal變量,那么訪問這個變量的每個線程都會有這個變量的本地副本,這也是ThreadLocal變量名的由來。他們可以使用 get() 和 set() 方法來獲取默認值或將其值更改為當前線程所存的副本的值,從而避免了線程安全問題。
再舉個簡單的例子:
比如有兩個人去寶屋收集寶物,這兩個共用一個袋子的話肯定會產生爭執(zhí),但是給他們兩個人每個人分配一個袋子的話就不會出現這樣的問題。如果把這兩個人比作線程的話,那么 ThreadLocal 就是用來避免這兩個線程競爭的。
ThreadLocal最終的變量是放在了當前線程的 ThreadLocalMap 中,并不是存在 ThreadLocal 上,ThreadLocal 可以理解為只是ThreadLocalMap的封裝,傳遞了變量值。 我們可以把 ThreadLocalMap 理解為ThreadLocal 類實現的定制化的 HashMap。ThrealLocal 類中可以通過Thread.currentThread()獲取到當前線程對象后,直接通過getMap(Thread t)可以訪問到該線程的ThreadLocalMap對象。
每個Thread中都具備一個ThreadLocalMap,而ThreadLocalMap可以存儲以ThreadLocal為 key ,Object 對象為 value 的鍵值對。
ThreadLocalMap(ThreadLocal<?>?firstKey,?Object?firstValue)?{...... }比如我們在同一個線程中聲明了兩個 ThreadLocal 對象的話,會使用 Thread內部都是使用僅有那個ThreadLocalMap 存放數據的,ThreadLocalMap的 key 就是 ThreadLocal對象,value 就是 ThreadLocal 對象調用set方法設置的值。
ThreadLocalMap是ThreadLocal的靜態(tài)內部類。
JVM
講一下 JVM 的內存結構(還問了每個區(qū)域的調優(yōu)配置參數,我蒙了)
Minor gc 和 Full gc 的區(qū)別,詳細介紹
方法區(qū)和永久代的關系?
JDK 1.8 HotSpot 的永久代為啥被徹底移除?有哪些常用參數?
主要進行 gc 的區(qū)域。永久代會發(fā)生 gc 嗎?元空間呢?
各種垃圾回收算法和回收器,說出自己的理解
zgc ?zgc vs g1?(我懵逼了~我只是聽過有這個東西,完全沒有去了解過)
---第 2 題參考答案---
周志明先生在《深入理解 Java 虛擬機》第二版中 P92 如是寫道:
“老年代 GC(Major GC/Full GC),指發(fā)生在老年代的 GC……”
上面的說法已經在《深入理解 Java 虛擬機》第三版中被改正過來了。感謝 R 大的回答:
總結:
針對 HotSpot VM 的實現,它里面的 GC 其實準確分類只有兩大種:
部分收集 (Partial GC):
新生代收集(Minor GC / Young GC):只對新生代進行垃圾收集;
老年代收集(Major GC / Old GC):只對老年代進行垃圾收集。需要注意的是 Major GC 在有的語境中也用于指代整堆收集;
混合收集(Mixed GC):對整個新生代和部分老年代進行垃圾收集。
整堆收集 (Full GC):收集整個 Java 堆和方法區(qū)。
---第 3 題參考答案---
方法區(qū)也被稱為永久代。很多人都會分不清方法區(qū)和永久代的關系,為此我也查閱了文獻。
《Java 虛擬機規(guī)范》只是規(guī)定了有方法區(qū)這么個概念和它的作用,并沒有規(guī)定如何去實現它。那么,在不同的 JVM 上方法區(qū)的實現肯定是不同的了。方法區(qū)和永久代的關系很像 Java 中接口和類的關系,類實現了接口,而永久代就是 HotSpot 虛擬機對虛擬機規(guī)范中方法區(qū)的一種實現方式。 也就是說,永久代是 HotSpot 的概念,方法區(qū)是 Java 虛擬機規(guī)范中的定義,是一種規(guī)范,而永久代是一種實現,一個是標準一個是實現,其他的虛擬機實現并沒有永久代這一說法。
---第 4 題參考答案---
JDK 1.8 的時候,方法區(qū)(HotSpot 的永久代)被徹底移除了(JDK1.7 就已經開始了),取而代之是元空間,元空間使用的是直接內存。
https://blogs.oracle.com/poonam/about-g1-garbage-collector,-permanent-generation-and-metaspace
下面是一些常用參數:
-XX:MetaspaceSize=N?//設置?Metaspace?的初始(和最小大小) -XX:MaxMetaspaceSize=N?//設置?Metaspace?的最大大小與永久代很大的不同就是,如果不指定大小的話,隨著更多類的創(chuàng)建,虛擬機會耗盡所有可用的系統(tǒng)內存。
為什么要將永久代 (PermGen) 替換為元空間 (MetaSpace) 呢?
https://plumbr.io/handbook/garbage-collection-in-java
1.整個永久代有一個 JVM 本身設置固定大小上限,無法進行調整,而元空間使用的是直接內存,受本機可用內存的限制,雖然元空間仍舊可能溢出,但是比原來出現的幾率會更小。
當你元空間溢出時會得到如下錯誤:java.lang.OutOfMemoryError: MetaSpace
你可以使用 -XX:MaxMetaspaceSize 標志設置最大元空間大小,默認值為 unlimited,這意味著它只受系統(tǒng)內存的限制。-XX:MetaspaceSize 調整標志定義元空間的初始大小如果未指定此標志,則 Metaspace 將根據運行時的應用程序需求動態(tài)地重新調整大小。
2.元空間里面存放的是類的元數據,這樣加載多少類的元數據就不由 MaxPermSize 控制了, 而由系統(tǒng)的實際可用空間來控制,這樣能加載的類就更多了。
3.在 JDK8,合并 HotSpot 和 JRockit 的代碼時, JRockit 從來沒有一個叫永久代的東西, 合并之后就沒有必要額外的設置這么一個永久代的地方了。
---第 5 題參考答案---
主要進行 gc 的區(qū)域是堆,就 HotSpot 虛擬機來說,永久代會發(fā)生 gc (full gc),但是,元空間使用的是直接內存不會發(fā)生 gc。
數據庫
講一下樂觀鎖和悲觀鎖;
說一下 MVCC
說一聚簇索引和非聚簇索引的有什么不同
關于索引的各種轟炸**(索引相關的知識太重要了!!!**)
網絡
為什么網絡要分層?
TCP/IP 4 層模型了解么?
http 是哪一層的協(xié)議?
http 和 https 什么區(qū)別
http2.0(不知道)
tcp 三次握手過程、滑動窗口是干什么的?
Mac 地址和 ip 地址的區(qū)別?既然有了 Mac 地址,為什么還要 ip 地址呢?
當你打開一個電商網站,都需要經歷哪些過程?
電子郵件的發(fā)送過程?
---第 1 題參考答案---
說到分層,我們先從我們平時使用框架開發(fā)一個后臺程序來說,我們往往會按照每一層做不同的事情的原則將系統(tǒng)分為 三層(復雜的系統(tǒng)分層可能會更多):
Repository(數據庫操作)
Service(業(yè)務操作)
Controller(數據交互)
復雜的系統(tǒng)需要分層,因為每一層都需要專注于一類事情。我們的網絡分層的原因也是一樣,每一層只專注于做一類事情。
為什么計算機網絡要分層呢? ,我們再來較為系統(tǒng)的說一說:
各層之間相互獨立:各層之間相互獨立,各層之間不需要關心其他層是如何實現的,只需要知道自己如何調用下層提供好的功能就可以了(可以簡單理解為接口調用)。這個和我們對開發(fā)時系統(tǒng)進行分層是一個道理。
提高了整體靈活性 :每一層都可以使用最適合的技術來實現,你只需要保證你提供的功能以及暴露的接口的規(guī)則沒有改變就行了。這個和我們平時開發(fā)系統(tǒng)的時候要求的高內聚、低耦合的原則也是可以對應上的。
大問題化小 :分層可以將復雜的網絡間題分解為許多比較小的、界線比較清晰簡單的小問題來處理和解決。這樣使得復雜的計算機網絡系統(tǒng)變得易于設計,實現和標準化。這個和我們平時開發(fā)的時候,一般會將系統(tǒng)功能分解,然后將復雜的問題分解為容易理解的更小的問題是相對應的,這些較小的問題具有更好的邊界(目標和接口)定義。
說到計算機網絡分層,我想到了計算機世界非常非常有名的一句話,這里分享一下:
計算機科學領域的任何問題都可以通過增加一個間接的中間層來解決,計算機整個體系從上到下都是按照嚴格的層次結構設計的。
Guide 哥注:如果一層不夠那就加兩層吧!
---第 2 題參考答案---
TCP/IP 4 層模型:
應用層
傳輸層
網絡層
網絡接口層
需要注意的是,我們并不能將 TCP/IP4 層模型 和 OSI7 層模型完全精確地匹配起來,不過可以簡單將兩者對應起來,如下圖所示:
TCP/IP 4層模型---第 3 題參考答案---
HTTP 協(xié)議 屬于應用層的協(xié)議。
HTTP 協(xié)議是基于 TCP 協(xié)議的,發(fā)送 HTTP 請求之前首先要建立 TCP 連接也就是要經歷 3 次握手。目前使用的 HTTP 協(xié)議大部分都是 1.1。在 1.1 的協(xié)議里面,默認是開啟了 Keep-Alive 的,這樣的話建立的連接就可以在多次請求中被復用了。
另外, HTTP 協(xié)議是”無狀態(tài)”的協(xié)議,它無法記錄客戶端用戶的狀態(tài) 一般我們都是通過 Session 來記錄客戶端用戶的狀態(tài)。
Spring
Spring AOP 和 IOC 的底層實現
Spring Boot 了解不?和 Spring 啥區(qū)別?
Spring Boot 的啟動類源碼有了解過嗎
其他
工作想 base 在哪里?為什么?
平時有什么興趣愛好?
自己未來有什么規(guī)劃?
平時是如何學習新技術的?(官網/書籍/博客/視頻)
一般遇到問題如何解決?(Google 和 Stackoverflow,雖然我平時很少用 Stackoverflow,但是還是和面試官說我經常用,哈哈哈!)
介不介意加班?(求生欲讓我回答不介意)
你有什么問題想問我?(我問了工作強度、項目上女生多不多)
總結
一定要準備好自我介紹。自我介紹盡量和簡歷上寫的更加豐富一點,突出自己的能力。
一面主要問的是項目,所以,在面試之前一定要對項目很熟悉!項目的優(yōu)化點、技術棧、架構圖等等都要搞清楚。
阿里面試總體感覺比較重視基礎,所以 Java 那些基本功一定要扎實。然后,網絡部分也要格外重視。
阿里面試官對于一些問題問的很深入,我沒有準備太好,結果導致 2 面就翻車了。
閑聊
Guide 的女讀者挺少的,10 個關注我的人中只有一個女性讀者。
最近在這篇文章:《最強(細)校招/社招求職指南:隔壁小姐姐已經收到字節(jié)意向書,你的秋招還沒開始?》中還逮到了一個拿到的字節(jié)意向書的女讀者(顏值又高,技術又好,太厲害了!),我真的不要太開心了!然后,就厚臉皮地去讓這位小姐姐幫忙寫一下面經(后續(xù)可能會安排上)。
還不是為了你們?我真是操碎了心啊!
往期推薦最簡單的6種防止數據重復提交的方法!(干貨)
漫畫:如何證明sleep不釋放鎖,而wait釋放鎖?
關注下方二維碼,每一天都有干貨!
總結
以上是生活随笔為你收集整理的被问哭了,一位小姐姐的阿里面经!(附部分答案)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 算法图解:如何判断括号是否有效?
- 下一篇: 第 6-1 课:Spring 核心 +