1. 程式人生 > >java面試(進階四篇)解答

java面試(進階四篇)解答

題目來自於網路,答案是筆者整理的。僅供參考,歡迎指正

來源: https://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247485779&idx=1&sn=3b06b9923df7f40f887ead8b8a53e50e&chksm=e9c5f0e2deb279f47fbfc3a12a70896bf95fa8c631939b87c85aea904785d10cb12667fa8724&scene=21&key=cf3fe9b79f0039bfe34c8540f1d4d5de82bd92d9536ebde316816880408f94640a5655f53e9e7cc11797ca27f4eee4a8a291910ef31ddaa1f6dfad4c648500c76477eff18997fabf8c722aef8b3aca4b&ascene=7&uin=MjM2OTQ3MDkzOQ%3D%3D&devicetype=Windows+7&version=6206021b&lang=zh_CN&pass_ticket=h97v%2FevjbeMS22Cec6mLcTFMVU17Iq0u%2FWtXpCY668m3AU7lLNOkKa9JdWj%2B8omE&winzoom=1

 

一、Java基礎

  • 為什麼JVM調優經常會將-Xms和-Xmx引數設定成一樣;

  • Java執行緒池的核心屬性以及處理流程;

  • Java記憶體模型,方法區存什麼;

  • CMS垃圾回收過程;

  • Full GC次數太多了,如何優化;

  • 直接記憶體如何管理的;

  • Java執行緒池的幾個引數的意義和實現機制;

  • Java執行緒池使用無界任務佇列和有界任務佇列的優劣對比;

  • CountDownLatch和CyclicBarrier的區別;

  • Java中有哪些同步方案(重量級鎖、顯式鎖、併發容器、併發同步器、CAS、volatile、AQS等)

  • 如果你的專案出現了記憶體洩露,怎麼監控這個問題呢;

  • 標記清除和標記整理的區別和優缺點,為何標記整理會發生stop the world;

  • 執行緒池,如何根據CPU的核數來設計執行緒大小,如果是計算機密集型的呢,如果是IO密集型的呢?

  • 讓你設計一個cache如何設計;

  • String中hashcode是怎麼實現的;

  • JDK中哪些實現了單例模式?

  • 多個執行緒同時讀寫,讀執行緒的數量遠遠⼤於寫執行緒,你認為應該如何解決併發的問題?你會選擇加什麼樣的鎖?

  • 執行緒池內的執行緒如果全部忙,提交⼀個新的任務,會發⽣什麼?佇列全部塞滿了之後,還是忙,再提交會發⽣什麼?

  • synchronized關鍵字鎖住的是什麼東西?在位元組碼中是怎麼表示的?在記憶體中的物件上表現為什麼?

  • wait/notify/notifyAll⽅法需不需要被包含在synchronized塊中?這是為什麼?

  • ExecutorService你一般是怎麼⽤的?是每個Service放一個還是個專案放一個?有什麼好處?

二、資料庫

  • InnoDB的插入緩衝和兩次寫的概率和意義;

  • 如果建了⼀個單列索引,查詢的時候查出2列,會⽤到這個單列索引嗎?(會用到)

  • 如果建了⼀個包含多個列的索引,查詢的時候只⽤了第⼀列,能不能⽤上這個索引?查三列呢?

  • 接上題,如果where條件後⾯帶有⼀個 i + 5 < 100 會使⽤到這個索引嗎?

  • like %aaa%會使⽤索引嗎? like aaa%呢?

  • drop、truncate、delete的區別?

  • 平時你們是怎麼監控資料庫的? 慢SQL是怎麼排查的?(慢查詢日誌)

  • 你們資料庫是否⽀持emoji表情,如果不⽀持,如何操作?選擇什麼編碼方式?如果支援一個表情佔幾個位元組?(utf8mb4);

  • 如果查詢很慢,你會想到的第⼀個⽅式是什麼?(資料庫索引)

三、Linux基礎

  • Linux下可以在/proc目錄下可以檢視CPU的核心數等;cat /proc/下邊會有很多系統核心資訊可供顯示; 

  • 說一下棧的記憶體是怎麼分配的;

  • Linux各個目錄有了解過嗎?/etc、/bin、/dev、/lib、/sbin這些常見的目錄主要作用是什麼?

  • 說一下棧幀的記憶體是怎麼分配的;

  • Linux下排查某個死迴圈的執行緒;

  • 動態連結和靜態連結的區別;

  • 程序的記憶體分佈;

  • 如何查詢一個程序開啟所有的檔案;

  • 說一下常使用的協議及其對應的埠;

  • 為什麼會有核心態,保護模式你知道嗎?

  • 檔案是怎麼在磁碟上儲存的?

  • 有了程序為何還要執行緒呢,不同程序和執行緒他們之間有什麼不同。(程序是資源管理的最小單位,執行緒是程式執行的最小單位。在作業系統設計上,從程序演化出執行緒,最主要的目的就是更好的支援SMP以及減小(程序/執行緒)上下文切換開銷。)

  • InnoDB聚集索引B+樹葉子節點和磁碟什麼順序相同;

  • 檔案系統,程序管理和排程,記憶體管理機制、虛地址保護模式;

四、網路基礎

  • HTTP1.0和HTTP1.1的區別;

  • DHCP如何實現分配IP的; 發現階段(DHCP客戶端在網路中廣播發送DHCP DISCOVER請求報文,發現DHCP伺服器,請求IP地址租約)、提供階段(DHCP伺服器通過DHCP OFFER報文向DHCP客戶端提供IP地址預分配)、選擇階段(DHCP客戶端通過DHCP REQUEST報文確認選擇第一個DHCP伺服器為它提供IP地址自動分配服務)和確認階段(被選擇的DHCP伺服器通過DHCP ACK報文把在DHCP OFFER報文中準備的IP地址租約給對應DHCP客戶端)。

  • OSI七層模型,每層都說下自己的理解和知道的,說的越多越好;

五、框架相關

  • Servlet如何保證單例模式,可不可以程式設計多例的哪?

  • Dubbo請求流程以及原理;

  • Spring框架如何實現事務的;

  • 如果一個接⼝有2個不同的實現, 那麼怎麼來Autowire一個指定的實現?(可以使用Qualifier註解限定要注入的Bean,也可以使用Qualifier和Autowire註解指定要獲取的bean,也可以使用Resource註解的name屬性指定要獲取的Bean)

  • Spring框架中需要引用哪些jar包,以及這些jar包的用途;

  • Spring Boot沒有放到web容器⾥為什麼能跑HTTP服務?

  • Spring中迴圈注入是什麼意思,可不可以解決,如何解決;

  • Spring的宣告式事務 @Transaction註解⼀般寫在什麼位置? 丟擲了異常會⾃動回滾嗎?有沒有辦法控制不觸發回滾?

  • MyBatis怎麼防止SQL注入;

  • Tomcat本身的引數你⼀般會怎麼調整?

  • 瞭解哪幾種序列化協議?如何選擇合適的序列化協議;

  • Redis漸進式rehash過程?

  • 比如我有個電商平臺,做每日訂單的異常檢測,服務端程式碼應該寫;

 

參考答案

一、Java基礎

 

1.為什麼JVM調優經常會將-Xms和-Xmx引數設定成一樣

    避免java堆自動擴充套件。

    java垃圾回收機制清理完堆區之後不需要重新計算堆區的大小而浪費資源

 

2.Java執行緒池的核心屬性以及處理流程

    流程:

    * 當執行緒池執行緒數<corePoolSize時,當新提交任務時,會建立一個執行緒來執行該任務

    * 當執行緒池執行緒數=corePoolSize時,再有任務提交,會將任務放置在workQueue裡,一個阻塞的佇列

    * 當佇列也放滿後,並且執行緒池數<maxPoolSize,會建立一個執行緒來執行新提交任務

    * 當執行緒池數=maxPoolSize時,此時若再有新任務提交,則執行拒絕策略

 

3.Java記憶體模型,方法區存什麼

    方法區主要存放靜態變數、常量、類元資料資訊

 

4.CMS垃圾回收過程  

1、初始標記(CMS Initial mark)    Stop the World   僅僅標記一下GC Roots能直接關聯到的物件,速度快
2、併發標記(CMS concurrent mark) 進行GC Roots Tracing(根搜尋演算法,判斷物件是否仍在使用中),時間長,不發生使用者程序停頓
3、重新標記(CMS remark)          Stop the World   修正併發標記期間因使用者程式繼續執行導致標記變動的那一部分物件的標記記錄,停頓時間較長,但遠比並發標記時間短
4、併發清除(CMS concurrent sweep) 清除的同時使用者程序會導致新的垃圾,時間長,不發生使用者程序停頓

5.Full GC次數太多了,如何優化

    MinorGC:發生在新生代的GC,當新生代沒有足夠空間來分配給新物件時就會發生

    FullGC:發生在老年代的GC,當老年代沒有足夠空間來分配給新物件就會發生;老年代需要為新生代預留一部分擔保空間,所以如果動態擔保空間不足也會發生一次FullGC

 

    觸發JVM進行FullGC的幾種情況及應對策略

    1)System.gc()方法的呼叫

        該方法會建議JVM進行FullGC,會增加FullGC的頻率,不建議使用該方法

        應對策略:通過設定XX:+ DisableExplicitGC來禁止RMI呼叫System.gc

 

    2)老年代空間不足

        老年代只有在新生代物件轉入及建立大物件、大陣列才會出現不足的情況

        應對策略:調優時應該儘量讓物件在MinorGC階段被回收;避免建立大物件

 

    3)方法區空間不足

        當系統中要載入的類、反射的類和呼叫的方法較多時,方法區有可能被佔滿,在未配置採用CMS GC的情況下也會發生FullGC

        應對策略:增大方法區空間大小;專為CMS GC

 

    看不明白的以下兩個:

4、CMS GC時出現promotion failed和concurrent mode failure

對於採用CMS進行老年代GC的程式而言,尤其要注意GC日誌中是否有promotion failed和concurrent mode failure兩種狀況,當這兩種狀況出現時可能

會觸發Full GC。
promotion failed是在進行Minor GC時,survivor space放不下、物件只能放入老年代,而此時老年代也放不下造成的;concurrent mode failure是在

執行CMS GC的過程中同時有物件要放入老年代,而此時老年代空間不足造成的(有時候“空間不足”是CMS GC時當前的浮動垃圾過多導致暫時性的空間不足觸發Full GC)。
對措施為:增大survivor space、老年代空間或調低觸發併發GC的比率,但在JDK 5.0+、6.0+的版本中有可能會由於JDK的bug29導致CMS在remark完畢

後很久才觸發sweeping動作。對於這種狀況,可通過設定-XX: CMSMaxAbortablePrecleanTime=5(單位為ms)來避免。


5、統計得到的Minor GC晉升到舊生代的平均大小大於老年代的剩餘空間

這是一個較為複雜的觸發情況,Hotspot為了避免由於新生代物件晉升到舊生代導致舊生代空間不足的現象,在進行Minor GC時,做了一個判斷,如果之

前統計所得到的Minor GC晉升到舊生代的平均大小大於舊生代的剩餘空間,那麼就直接觸發Full GC。
例如程式第一次觸發Minor GC後,有6MB的物件晉升到舊生代,那麼當下一次Minor GC發生時,首先檢查舊生代的剩餘空間是否大於6MB,如果小於6MB,

則執行Full GC。
當新生代採用PS GC時,方式稍有不同,PS GC是在Minor GC後也會檢查,例如上面的例子中第一次Minor GC後,PS GC會檢查此時舊生代的剩餘空間是否

大於6MB,如小於,則觸發對舊生代的回收。
除了以上4種狀況外,對於使用RMI來進行RPC或管理的Sun JDK應用而言,預設情況下會一小時執行一次Full GC。可通過在啟動時通過- java -

Dsun.rmi.dgc.client.gcInterval=3600000來設定Full GC執行的間隔時間或通過-XX:+ DisableExplicitGC來禁止RMI呼叫System.gc。
--------------------- 
作者:end 
來源:CSDN 
原文:https://blog.csdn.net/endlu/article/details/51144918 
版權宣告:本文為博主原創文章,轉載請附上博文連結!

6.直接記憶體如何管理的

    NIO的Buffer提供了一個可以不經過JVM記憶體直接訪問系統實體記憶體的類-DirectBuffer

    DirectBuffer繼承自ByteBuffer,但和普通的ByteBuffer不同。

        普通的ByteBuffer分配在堆記憶體上,其最大大小受限於最大堆記憶體的限制;

        而DirectBuffer直接分配在實體記憶體上,並不佔用堆記憶體,其可申請的最大記憶體受限於作業系統

 

    直接記憶體的讀寫操作比普通Buffer快,但它的建立銷燬比普通Buffer慢;因此直接記憶體適合於使用大記憶體空間並且頻繁訪問的場合,不適合頻繁釋放申請記憶體的場合

 

    注意:DirectBuffer並沒有真正向OS申請分配記憶體,其最終還是通過呼叫Unsafe的allocateMemory()來進行記憶體分配。不過JVM對Direct Memory可申請的大小也有限制,可用-XX:MaxDirectMemorySize=1M設定,這部分記憶體不受JVM垃圾回收管理。

 

    

7.Java執行緒池的幾個引數的意義和實現機制

    參考2

 

8.Java執行緒池使用無界任務佇列和有界任務佇列的優劣對比

    無界佇列除非系統資源耗盡,否則不會出現拒絕任務入隊的情況。

    若任務建立和處理的差異很大,那麼無界佇列會快速增長,直到耗盡系統資源    

 

9.CountDownLatch和CyclicBarrier的區別

    * CountDownLatch:閉鎖的功能類似於一扇門,在閉鎖達到結束狀態之前,門是一直關閉的,沒有任何執行緒能夠通過。當達到結束狀態時,

這扇門會開啟並允許所有的執行緒通過。閉鎖可以用來確保某些活動直到其他活動結束後才繼續執行

    * CyclicBarrier:柵欄類似於閉鎖,它能阻止一組執行緒直到某個事件發生。

    不同點在於:閉鎖做減法計數,柵欄做加法計數;閉鎖是一次性的,柵欄可重複使用;閉鎖用於等待事件,柵欄用於等待其他執行緒
 

 

10.Java中有哪些同步方案

    Synchronized、ReentrantLock、同步容器、CAS、volatile等

 

11.如果你的專案出現了記憶體洩露,怎麼監控這個問題呢

    // TODO

 

12.標記清除和標記整理的區別和優缺點,為何標記整理會發生stop the world

    標記清除:會將需要回收的記憶體標記下來,然後進行清除。會造成記憶體碎片,大量的記憶體碎片會導致另一次GC

    標記整理:標記過程與標記清除類似,整理過程則是將所有存活的物件向一側移動,然後直接清除邊界以外的記憶體

 

13.執行緒池,如何根據CPU的核數來設計執行緒大小,如果是計算機密集型的呢,如果是IO密集型的呢

    計算密集型:在N CPU的處理器上工作,N+1個執行緒最優

    IO密集型:執行緒數=((執行緒等待時間+執行緒CPU時間)/執行緒CPU時間)*CPU數目

 

14.讓你設計一個cache如何設計

    主要是想知道如何設計cache的演算法

    cache的演算法設計常見的有:FIFO(先進先出)、LRU(least recently used最近最少使用)、LFU(least Frequently used最不經常使用)

    具體可參考:https://www.cnblogs.com/davidwang456/p/4001342.html 

 

15.String中hashcode是怎麼實現的

    hashCode的計算應用在集合中的時候,我們通過hashCode來比較兩個物件是否相等,如果hashCode不相等則兩個物件一定不等。如果hashCode相等的話再呼叫物件的equals方法來比較。

    由於hashCode的比較比equals的比較快的多,所以我們在設計hashCode的時候要儘可能的讓hashCode不重複。

 

    String.hashCode()原始碼如下:

    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

    更多可參考:https://blog.csdn.net/myspacedemen/article/details/53353480  

 

16.JDK中哪些實現了單例模式

    java.lang.Runtime,可以控制JVM的狀態和行為

    java.lang.reflect.Proxy感覺不像單例模式

 

17.多個執行緒同時讀寫,讀執行緒的數量遠遠⼤於寫執行緒,你認為應該如何解決併發的問題?你會選擇加什麼樣的鎖

    ReentrantReadWriteLock讀寫鎖

 

18.執行緒池內的執行緒如果全部忙,提交⼀個新的任務,會發⽣什麼?佇列全部塞滿了之後,還是忙,再提交會發⽣什麼?

   執行緒池內的執行緒如果全部忙,提交⼀個新的任務,會將任務新增到佇列中

   佇列全部塞滿了之後,還是忙,再提交會建立新的執行緒執行任務,直到執行緒數=maxPoolSize

   之後在提交會執行拒絕策略  

 

19.synchronized關鍵字鎖住的是什麼東西?在位元組碼中是怎麼表示的?在記憶體中的物件上表現為什麼?

    // TODO    

 

20.wait/notify/notifyAll⽅法需不需要被包含在synchronized塊中?這是為什麼?

    需要,只有持有鎖的執行緒才能夠呼叫物件的wait、notify等這些方法

 

21.ExecutorService你一般是怎麼⽤的?是每個Service放一個還是個專案放一個?有什麼好處?

    最好不要按專案來放,按不同的任務型別來放置最好。

    有的任務執行的時間長,有的任務執行的時間短,如果都使用一個執行緒池的話,執行任務時間長的容易阻塞住執行緒,導致其他執行時間短的任務無法獲取到執行緒

 

 

未完待續...