一位讀者小姐姐的阿里Java後臺面經分享,快被問哭了!(附部分問題詳解)

這篇文章是一位 女讀者 (加粗!太難得)的面試阿里的經歷分享,雖然第二面面完就失敗了,但是這樣的經歷對自己幫助還是很大的。

下面的一些問題非常具有代表性,部分問題我簡單做了修改(有些問題表述的不那麼準確)。這些問題對於大家用於自測或者準備面試都很有幫助。

我只給出了少部分問題的參考答案,因爲自己真的抽不出有時間來把每一個問題都細心解答一遍了。單單是回答了下面的少部分問題,就從昨晚 9 點一直忙到 12 點半。

有答案需求的小夥伴,評論區安排,需要的人多的話,我這週末花時間把一份頂好的參考答案都整出來!

小聲 BB:寫參考答案其實挺難的,相比於面試的時候回答問題來說。很多面試官自己問的問題可能連自己都不清楚,哈哈哈!單單是回答了下面的少部分問題,就從昨晚 9 點一直忙到 12 點半。

自我介紹就不說了,每一面都會讓你說。

項目相關

這個面試前肯定要準備的

  1. 介紹一下你簡歷上寫的項目?自己主要做了什麼?(簡歷上雖然寫了,但是面試官還是問了
  2. 你覺得項目裏給你最大的挑戰是什麼?遇到了什麼問題?如何解決的?從中學到了什麼?
  3. 項目的架構圖能畫一下不?(一個很 low 的後臺網站
  4. 覺得項目有哪些地方可以改進完善?(我說可以加一個 redis 緩存把熱點數據緩存起來
  5. 爲什麼要用 Nginx?有啥用?優缺點?
  6. 有沒有遇到過內存泄漏的場景?

Java 基礎

  1. StringBuilder 和 StringBuffer(StringBuffer 是線程安全的,StringBuilder 是不安全的
  2. 如何實現靜態代理?有啥缺陷?
  3. 動態代理的作用?在哪些地方用到了?(AOP、RPC 框架中都有用到
  4. JDK 的動態代理和 CGLIB 有什麼區別?
  5. 談談對 Java 註解的理解,解決了什麼問題?
  6. Java 反射?反射有什麼缺點?你是怎麼理解反射的(爲什麼框架需要反射)?

---第 4 題參考答案---

JDK 動態代理只能只能代理實現了接口的類,而 CGLIB 可以代理未實現任何接口的類。 另外, CGLIB 動態代理是通過生成一個被代理類的子類來攔截被代理類的方法調用,因此不能代理聲明爲 final 類型的類和方法。就二者的效率來說,大部分情況都是 JDK 動態代理更優秀,隨着 JDK 版本的升級,這個優勢更加明顯。

---第 5 題參考答案---

Java 語言中的類、方法、變量、參數和包等都可以註解標記,程序運行期間我們可以獲取到相應的註解以及註解中定義的內容,這樣可以幫助我們做一些事情。比如說 Spring 中如果檢測到說你的類被 @Component註解標記的話,Spring 容器在啓動的時候就會把這個類歸爲自己管理,這樣你就可以通過 @Autowired註解注入這個對象了。

---第 6 題參考答案---

反射介紹:

JAVA 反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱爲 java 語言的反射機制。

反射的優缺點如下:

  • 優點: 運行期類型的判斷,動態加載類,提高代碼靈活度。
  • 缺點: 1,性能瓶頸:反射相當於一系列解釋操作,通知 JVM 要做的事情,性能比直接的 java 代碼要慢很多。2,安全問題,讓我們可以動態操作改變類的屬性同時也增加了類的安全隱患。

爲什麼框架需要反射技術?

在我們平時的項目開發過程中,基本上很少會直接使用到反射機制,但這不能說明反射機制沒有用,實際上有很多設計、開發都與反射機制有關,例如模塊化的開發,通過反射去調用對應的字節碼;動態代理設計模式也採用了反射機制,還有我們日常使用的 Spring/Hibernate 等框架也大量使用到了反射機制。

舉例:

  1. 我們在使用 JDBC 連接數據庫時使用 Class.forName()通過反射加載數據庫的驅動程序;
  2. Spring 框架的 IOC(動態加載管理 Bean)創建對象以及 AOP(動態代理)功能都和反射有聯繫;
  3. 動態配置實例的屬性;
  4. ......

更多 Java 相關的問題,請參考這篇頂好頂完善的文章: [恐怖:這份Github神仙面試筆記,簡直把所有Java知識面試題寫出來了)附 PDF 版 !(https://www.jianshu.com/p/ba07aafda9a9 )

集合框架

  1. HashMap 的底層實現、JDK 1.8 的時候爲啥將鏈表轉換成紅黑樹?、HashMap 的負載因子、HashMap 和 Hashtable 的區別?
  2. 有哪些集合是線程不安全的?怎麼解決呢?
  3. 什麼是快速失敗(fail-fast)、能舉個例子嗎?、什麼是安全失敗(fail-safe)呢?

多線程

  1. 在多線程情況下如何保證線程安全
  2. synchronized 作用,底層實現
  3. ReetrantLock 和 synchronized 的區別
  4. AQS
  5. 線程池作用?Java 線程池有哪些參數?阻塞隊列有幾種?拒絕策略有幾種?
  6. 線程死鎖
  7. ThreadLocal 是什麼,應用場景是什麼,原理是怎樣的
  8. 介紹一下 Java 有哪些鎖(synchronized、juc 提供的鎖如 ReentrantLock、CountDownLatch、CyclicBarrier、Semaphore 等)

---第 6 題參考答案---

線程死鎖描述的是這樣一種情況:多個線程同時被阻塞,它們中的一個或者全部都在等待某個資源被釋放。由於線程被無限期地阻塞,因此程序不可能正常終止。

如下圖所示,線程 A 持有資源 2,線程 B 持有資源 1,他們同時都想申請對方的資源,所以這兩個線程就會互相等待而進入死鎖狀態。

---第 7 題參考答案---

通常情況下,我們創建的變量是可以被任何一個線程訪問並修改的。如果想實現每一個線程都有自己的專屬本地變量該如何解決呢? JDK 中提供的ThreadLocal類正是爲了解決這樣的問題。 ThreadLocal類主要解決的就是讓每個線程綁定自己的值,可以將ThreadLocal類形象的比喻成存放數據的盒子,盒子中可以存儲每個線程的私有數據。

如果你創建了一個ThreadLocal變量,那麼訪問這個變量的每個線程都會有這個變量的本地副本,這也是ThreadLocal變量名的由來。他們可以使用 get()set() 方法來獲取默認值或將其值更改爲當前線程所存的副本的值,從而避免了線程安全問題。

再舉個簡單的例子:

比如有兩個人去寶屋收集寶物,這兩個共用一個袋子的話肯定會產生爭執,但是給他們兩個人每個人分配一個袋子的話就不會出現這樣的問題。如果把這兩個人比作線程的話,那麼 ThreadLocal 就是用來避免這兩個線程競爭的。

ThreadLocal最終的變量是放在了當前線程的 ThreadLocalMap 中,並不是存在 ThreadLocal 上,ThreadLocal 可以理解爲只是ThreadLocalMap的封裝,傳遞了變量值。 我們可以把 ThreadLocalMap 理解爲ThreadLocal 類實現的定製化的 HashMapThrealLocal 類中可以通過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方法設置的值。

ThreadLocalMapThreadLocal的靜態內部類。

JVM

  1. 講一下 JVM 的內存結構(還問了每個區域的調優配置參數,我蒙了)
  2. Minor gc 和 Full gc 的區別,詳細介紹
  3. 方法區和永久代的關係?
  4. JDK 1.8 HotSpot 的永久代爲啥被徹底移除?有哪些常用參數?
  5. 主要進行 gc 的區域。永久代會發生 gc 嗎?元空間呢?
  6. 各種垃圾回收算法和回收器,說出自己的理解
  7. zgc ?zgc vs g1?(我懵逼了~我只是聽過有這個東西,完全沒有去了解過)

---第 2 題參考答案---

周志明先生在《深入理解 Java 虛擬機》第二版中 P92 如是寫道:

“老年代 GC(Major GC/Full GC),指發生在老年代的 GC……”

上面的說法已經在《深入理解 Java 虛擬機》第三版中被改正過來了。感謝 R 大的回答:

總結:

針對 HotSpot VM 的實現,它裏面的 GC 其實準確分類只有兩大種:

部分收集 (Partial GC):

  • 新生代收集(Minor GC / Young GC):只對新生代進行垃圾收集;
  • 老年代收集(Major GC / Old GC):只對老年代進行垃圾收集。需要注意的是 Major GC 在有的語境中也用於指代整堆收集;
  • 混合收集(Mixed GC):對整個新生代和部分老年代進行垃圾收集。

整堆收集 (Full GC):收集整個 Java 堆和方法區。

---第 3 題參考答案---

方法區也被稱爲永久代。很多人都會分不清方法區和永久代的關係,爲此我也查閱了文獻。

《Java 虛擬機規範》只是規定了有方法區這麼個概念和它的作用,並沒有規定如何去實現它。那麼,在不同的 JVM 上方法區的實現肯定是不同的了。 方法區和永久代的關係很像 Java 中接口和類的關係,類實現了接口,而永久代就是 HotSpot 虛擬機對虛擬機規範中方法區的一種實現方式。 也就是說,永久代是 HotSpot 的概念,方法區是 Java 虛擬機規範中的定義,是一種規範,而永久代是一種實現,一個是標準一個是實現,其他的虛擬機實現並沒有永久代這一說法。

---第 4 題參考答案---

JDK 1.8 的時候,方法區(HotSpot 的永久代)被徹底移除了(JDK1.7 就已經開始了),取而代之是元空間,元空間使用的是直接內存。

下面是一些常用參數:

-XX:MetaspaceSize=N //設置 Metaspace 的初始(和最小大小)
-XX:MaxMetaspaceSize=N //設置 Metaspace 的最大大小

與永久代很大的不同就是,如果不指定大小的話,隨着更多類的創建,虛擬機會耗盡所有可用的系統內存。

爲什麼要將永久代 (PermGen) 替換爲元空間 (MetaSpace) 呢?

1.整個永久代有一個 JVM 本身設置固定大小上限,無法進行調整,而元空間使用的是直接內存,受本機可用內存的限制,雖然元空間仍舊可能溢出,但是比原來出現的機率會更小。

當你元空間溢出時會得到如下錯誤: java.lang.OutOfMemoryError: MetaSpace

你可以使用 -XX:MaxMetaspaceSize 標誌設置最大元空間大小,默認值爲 unlimited,這意味着它只受系統內存的限制。-XX:MetaspaceSize 調整標誌定義元空間的初始大小如果未指定此標誌,則 Metaspace 將根據運行時的應用程序需求動態地重新調整大小。

2.元空間裏面存放的是類的元數據,這樣加載多少類的元數據就不由 MaxPermSize 控制了, 而由系統的實際可用空間來控制,這樣能加載的類就更多了。

3.在 JDK8,合併 HotSpot 和 JRockit 的代碼時, JRockit 從來沒有一個叫永久代的東西, 合併之後就沒有必要額外的設置這麼一個永久代的地方了。

---第 5 題參考答案---

主要進行 gc 的區域是堆,就 HotSpot 虛擬機來說,永久代會發生 gc (full gc),但是,元空間使用的是直接內存不會發生 gc。

數據庫

  1. 講一下樂觀鎖和悲觀鎖;
  2. 說一下 MVCC
  3. 說一聚簇索引和非聚簇索引的有什麼不同
  4. 關於索引的各種轟炸(索引相關的知識太重要了!!!)

網絡

  1. 爲什麼網絡要分層?
  2. TCP/IP 4 層模型瞭解麼?
  3. http 是哪一層的協議?
  4. http 和 https 什麼區別
  5. http2.0(不知道
  6. tcp 三次握手過程、滑動窗口是幹什麼的?
  7. Mac 地址和 ip 地址的區別?既然有了 Mac 地址,爲什麼還要 ip 地址呢?
  8. 當你打開一個電商網站,都需要經歷哪些過程?
  9. 電子郵件的發送過程?

---第 1 題參考答案---

說到分層,我們先從我們平時使用框架開發一個後臺程序來說,我們往往會按照每一層做不同的事情的原則將系統分爲 三層(複雜的系統分層可能會更多):

  1. Repository(數據庫操作)
  2. Service(業務操作)
  3. Controller(數據交互)

複雜的系統需要分層,因爲每一層都需要專注於一類事情。我們的網絡分層的原因也是一樣,每一層只專注於做一類事情。

爲什麼計算機網絡要分層呢? ,我們再來較爲系統的說一說:

  1. 各層之間相互獨立:各層之間相互獨立,各層之間不需要關心其他層是如何實現的,只需要知道自己如何調用下層提供好的功能就可以了(可以簡單理解爲接口調用)。這個和我們對開發時系統進行分層是一個道理。
  2. 提高了整體靈活性 :每一層都可以使用最適合的技術來實現,你只需要保證你提供的功能以及暴露的接口的規則沒有改變就行了。這個和我們平時開發系統的時候要求的高內聚、低耦合的原則也是可以對應上的。
  3. 大問題化小 : 分層可以將複雜的網絡間題分解爲許多比較小的、界線比較清晰簡單的小問題來處理和解決。這樣使得複雜的計算機網絡系統變得易於設計,實現和標準化。 這個和我們平時開發的時候,一般會將系統功能分解,然後將複雜的問題分解爲容易理解的更小的問題是相對應的,這些較小的問題具有更好的邊界(目標和接口)定義。

說到計算機網絡分層,我想到了計算機世界非常非常有名的一句話,這裏分享一下:

計算機科學領域的任何問題都可以通過增加一個間接的中間層來解決,計算機整個體系從上到下都是按照嚴格的層次結構設計的。

如果一層不夠那就加兩層吧!*

---第 2 題參考答案---

TCP/IP 4 層模型:

  1. 應用層
  2. 傳輸層
  3. 網絡層
  4. 網絡接口層

需要注意的是,我們並不能將 TCP/IP4 層模型 和 OSI7 層模型完全精確地匹配起來,不過可以簡單將兩者對應起來,如下圖所示:

---第 3 題參考答案---

HTTP 協議 屬於應用層的協議。

HTTP 協議是基於 TCP 協議的,發送 HTTP 請求之前首先要建立 TCP 連接也就是要經歷 3 次握手。目前使用的 HTTP 協議大部分都是 1.1。在 1.1 的協議裏面,默認是開啓了 Keep-Alive 的,這樣的話建立的連接就可以在多次請求中被複用了。

另外, HTTP 協議是”無狀態”的協議,它無法記錄客戶端用戶的狀態 一般我們都是通過 Session 來記錄客戶端用戶的狀態。

Spring

  1. Spring AOP 和 IOC 的底層實現
  2. Spring Boot 瞭解不?和 Spring 啥區別?
  3. Spring Boot 的啓動類源碼有了解過嗎

其他

  1. 工作想 base 在哪裏?爲什麼?
  2. 平時有什麼興趣愛好?
  3. 自己未來有什麼規劃?
  4. 平時是如何學習新技術的?(官網/書籍/博客/視頻)
  5. 一般遇到問題如何解決?(Google 和 Stackoverflow,雖然我平時很少用 Stackoverflow,但是還是和麪試官說我經常用,哈哈哈!)
  6. 介不介意加班?(求生欲讓我回答不介意)
  7. 你有什麼問題想問我?(我問了工作強度、項目上女生多不多

總結

  1. 一定要準備好自我介紹。自我介紹儘量和簡歷上寫的更加豐富一點,突出自己的能力。
  2. 一面主要問的是項目,所以,在面試之前一定要對項目很熟悉!項目的優化點、技術棧、架構圖等等都要搞清楚。
  3. 阿里面試總體感覺比較重視基礎,所以 Java 那些基本功一定要紮實。然後,網絡部分也要格外重視。
  4. 阿里面試官對於一些問題問的很深入,我沒有準備太好,結果導致 2 面就翻車了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章