【Java開發面試系列】JVM相關面試題(精選)

【Java開發面試系列】JVM相關面試題(精選)

文章目錄

  • 【Java開發面試系列】JVM相關面試題(精選)
    • 前言
      • 一、JVM組成
      • 二、類加載器
      • 三、垃圾回收
      • 四、JVM實踐(調優)

🌈你好呀!我是 山頂風景獨好
💝歡迎來到我的博客,很高興能夠在這里和您見面!
💝希望您在這里可以感受到一份輕松愉快的氛圍!
💝不僅可以獲得有趣的內容和知識,也可以暢所欲言、分享您的想法和見解。
🚀 歡迎一起踏上探險之旅,挖掘無限可能,共同成長!

前言

在尋求面試資料的旅途中,我有幸發現了黑馬老師所撰寫的寶貴資料,其內容詳盡且見解獨到,對我而言無疑是一筆巨大的財富。我深感其智慧與經驗的深厚,并在此過程中受益匪淺。

為了深入學習和鞏固這些寶貴的知識,我精心整理了所有的面試題目,并編輯成這一系列的博客。這不僅是我個人學習的讀書筆記,更是我對黑馬老師無私奉獻和深厚學識的崇高敬意。

同時,我也希望通過分享這些博客,將這份知識與智慧傳遞給更多的同學,共同提高我們的面試技巧和知識儲備

  • 本系列文章定位:
    【Java開發面試系列】MySQL相關面試題(精選)
    【Java開發面試系列】Redis相關面試題(精選)
    【Java開發面試系列】框架相關面試題(精選)
    【Java開發面試系列】微服務相關面試題(精選)
    【Java開發面試系列】消息中間件相關面試題(精選)
    【Java開發面試系列】常見集合相關面試題(精選)
    【Java開發面試系列】并發編程相關面試題(精選)
    【Java開發面試系列】JVM相關面試題(精選)
    【Java開發面試系列】設計模式相關面試題(精選)
    【Java開發面試系列】技術場景相關面試題(精選)

一、JVM組成

面試官:JVM由那些部分組成,運行流程是什么?

候選人:

嗯,好的~~

在JVM中共有四大部分,分別是ClassLoader(類加載器)、Runtime Data Area(運行時數據區,內存分區)、Execution Engine(執行引擎)、Native Method Library(本地庫接口)

它們的運行流程是:

  • 第一,類加載器(ClassLoader)把Java代碼轉換為字節碼

  • 第二,運行時數據區(Runtime Data Area)把字節碼加載到內存中,而字節碼文件只是JVM的一套指令集規范,并不能直接交給底層系統去執行,而是有執行引擎運行

  • 第三,執行引擎(Execution Engine)將字節碼翻譯為底層系統指令,再交由CPU執行去執行,此時需要調用其他語言的本地庫接口(Native Method Library)來實現整個程序的功能。


面試官:好的,你能詳細說一下 JVM 運行時數據區嗎?

候選人:

嗯,好~

運行時數據區包含了堆、方法區、棧、本地方法棧、程序計數器這幾部分,每個功能作用不一樣。

  • 堆解決的是對象實例存儲的問題,垃圾回收器管理的主要區域。
  • 方法區可以認為是堆的一部分,用于存儲已被虛擬機加載的信息,常量、靜態變量、即時編譯器編譯后的代碼。
  • 棧解決的是程序運行的問題,棧里面存的是棧幀,棧幀里面存的是局部變量表、操作數棧、動態鏈接、方法出口等信息。
  • 本地方法棧與棧功能相同,本地方法棧執行的是本地方法,一個Java調用非Java代碼的接口。
  • 程序計數器(PC寄存器)程序計數器中存放的是當前線程所執行的字節碼的行數。JVM工作時就是通過改變這個計數器的值來選取下一個需要執行的字節碼指令。

面試官:好的,你再詳細介紹一下程序計數器的作用?

候選人:

嗯,是這樣~~

java虛擬機對于多線程是通過線程輪流切換并且分配線程執行時間。在任何的一個時間點上,一個處理器只會處理執行一個線程,如果當前被執行的這個線程它所分配的執行時間用完了【掛起】。處理器會切換到另外的一個線程上來進行執行。并且這個線程的執行時間用完了,接著處理器就會又來執行被掛起的這個線程。這時候程序計數器就起到了關鍵作用,程序計數器在來回切換的線程中記錄他上一次執行的行號,然后接著繼續向下執行。


面試官:你能給我詳細的介紹Java堆嗎?

候選人:

  • 好的~

  • Java中的堆術語線程共享的區域。主要用來保存對象實例,數組等,當堆中沒有內存空間可分配給實例,也無法再擴展時,則拋出OutOfMemoryError異常。

?在JAVA8中堆內會存在年輕代、老年代

  1. Young區被劃分為三部分,Eden區和兩個大小嚴格相同的Survivor區,其中,Survivor區間中,某一時刻只有其中一個是被使用的,另外一個留做垃圾收集時復制對象用。在Eden區變滿的時候, GC就會將存活的對象移到空閑的Survivor區間中,根據JVM的策略,在經過幾次垃圾收集后,任然存活于Survivor的對象將被移動到Tenured區間。

  2. Tenured區主要保存生命周期長的對象,一般是一些老的對象,當一些對象在Young復制轉移一定的次數以后,對象就會被轉移到Tenured區。


面試官:能不能解釋一下方法區?

候選人:

好的~

與虛擬機棧類似。本地方法棧是為虛擬機執行本地方法時提供服務的。不需要進行GC。本地方法一般是由其他語言編寫。


面試官:你聽過直接內存嗎?

候選人:

嗯~~

  • 它又叫做堆外內存線程共享的區域,在 Java 8 之前有個永久代的概念,實際上指的是 HotSpot 虛擬機上的永久代,它用永久代實現了 JVM 規范定義的方法區功能,主要存儲類的信息,常量,靜態變量,即時編譯器編譯后代碼等,這部分由于是在堆中實現的,受 GC 的管理,不過由于永久代有 -XX:MaxPermSize 的上限,所以如果大量動態生成類(將類信息放入永久代),很容易造成 OOM,有人說可以把永久代設置得足夠大,但很難確定一個合適的大小,受類數量,常量數量的多少影響很大。

  • 所以在 Java 8 中就把方法區的實現移到了本地內存中的元空間中,這樣方法區就不受 JVM 的控制了,也就不會進行 GC,也因此提升了性能。


面試官:什么是虛擬機棧

候選人:

虛擬機棧是描述的是方法執行時的內存模型,是線程私有的,生命周期與線程相同,每個方法被執行的同時會創建棧楨。保存執行方法時的局部變量、動態連接信息、方法返回地址信息等等。方法開始執行的時候會進棧,方法執行完會出棧【相當于清空了數據】,所以這塊區域不需要進行 GC


面試官:能說一下堆棧的區別是什么嗎?

候選人:

嗯,好的,有這幾個區別

  • 第一,棧內存一般會用來存儲局部變量和方法調用,但堆內存是用來存儲Java對象和數組的的。堆會GC垃圾回收,而棧不會。

  • 第二、棧內存是線程私有的,而堆內存是線程共有的。

  • 第三、兩者異常錯誤不同,但如果棧內存或者堆內存不足都會拋出異常。

  • 棧空間不足:java.lang.StackOverFlowError。

  • 堆空間不足:java.lang.OutOfMemoryError。

二、類加載器

面試官:什么是類加載器,類加載器有哪些?

候選人:

嗯,是這樣的

JVM只會運行二進制文件,而類加載器(ClassLoader)的主要作用就是將字節碼文件加載到JVM中,從而讓Java程序能夠啟動起來。

常見的類加載器有4個

  • 第一個是啟動類加載器(BootStrap ClassLoader):其是由C++編寫實現。用于加載JAVA_HOME/jre/lib目錄下的類庫。

  • 第二個是擴展類加載器(ExtClassLoader):該類是ClassLoader的子類,主要加載JAVA_HOME/jre/lib/ext目錄中的類庫。

  • 第三個是應用類加載器(AppClassLoader):該類是ClassLoader的子類,主要用于加載classPath下的類,也就是加載開發者自己編寫的Java類。

  • 第四個是自定義類加載器:開發者自定義類繼承ClassLoader,實現自定義類加載規則。


面試官:說一下類裝載的執行過程?

候選人:

嗯,這個過程還是挺多的。

類從加載到虛擬機中開始,直到卸載為止,它的整個生命周期包括了:加載、驗證、準備、解析、初始化、使用和卸載這7個階段。其中,驗證、準備和解析這三個部分統稱為連接(linking)

  1. 加載:查找和導入class文件

  2. 驗證:保證加載類的準確性

  3. 準備:為類變量分配內存并設置類變量初始值

  4. 解析:把類中的符號引用轉換為直接引用

  5. 初始化:對類的靜態變量,靜態代碼塊執行初始化操作

  6. 使用:JVM 開始從入口方法開始執行用戶的程序代碼

  7. 卸載:當用戶程序代碼執行完畢后,JVM 便開始銷毀創建的 Class 對象,最后負責運行的 JVM 也退出內存


面試官:什么是雙親委派模型?

候選人:

嗯,它是是這樣的。

如果一個類加載器收到了類加載的請求,它首先不會自己嘗試加載這個類,而是把這請求委派給父類加載器去完成,每一個層次的類加載器都是如此,因此所有的加載請求最終都應該傳說到頂層的啟動類加載器中,只有當父類加載器返回自己無法完成這個加載請求(它的搜索返回中沒有找到所需的類)時,子類加載器才會嘗試自己去加載


面試官:JVM為什么采用雙親委派機制

候選人:

主要有兩個原因。

  • 第一、通過雙親委派機制可以避免某一個類被重復加載,當父類已經加載后則無需重復加載,保證唯一性。

  • 第二、為了安全,保證類庫API不會被修改

三、垃圾回收

面試官:簡述Java垃圾回收機制?(GC是什么?為什么要GC)

候選人:

  • 嗯,是這樣~~

  • 為了讓程序員更專注于代碼的實現,而不用過多的考慮內存釋放的問題,所以,在Java語言中,有了自動的垃圾回收機制,也就是我們熟悉的GC(Garbage Collection)。

  • 有了垃圾回收機制后,程序員只需要關心內存的申請即可,內存的釋放由系統自動識別完成。

  • 在進行垃圾回收時,不同的對象引用類型,GC會采用不同的回收時機


面試官:強引用、軟引用、弱引用、虛引用的區別?

候選人:

  • 嗯嗯~

  • 強引用最為普通的引用方式,表示一個對象處于有用且必須的狀態,如果一個對象具有強引用,則GC并不會回收它。即便堆中內存不足了,寧可出現OOM,也不會對其進行回收

  • 軟引用表示一個對象處于有用且非必須狀態,如果一個對象處于軟引用,在內存空間足夠的情況下,GC機制并不會回收它,而在內存空間不足時,則會在OOM異常出現之間對其進行回收。但值得注意的是,因為GC線程優先級較低,軟引用并不會立即被回收。

  • 弱引用表示一個對象處于可能有用且非必須的狀態。在GC線程掃描內存區域時,一旦發現弱引用,就會回收到弱引用相關聯的對象。對于弱引用的回收,無關內存區域是否足夠,一旦發現則會被回收。同樣的,因為GC線程優先級較低,所以弱引用也并不是會被立刻回收。

  • 虛引用表示一個對象處于無用的狀態。在任何時候都有可能被垃圾回收。虛引用的使用必須和引用隊列Reference Queue聯合使用


面試官:對象什么時候可以被垃圾器回收

候選人:

  • 如果一個或多個對象沒有任何的引用指向它了,那么這個對象現在就是垃圾,如果定位了垃圾,則有可能會被垃圾回收器回收。

  • 如果要定位什么是垃圾,有兩種方式來確定,第一個是引用計數法,第二個是可達性分析算法

  • 通常都使用可達性分析算法來確定是不是垃圾


面試官: JVM 垃圾回收算法有哪些?

候選人:

我記得一共有四種,分別是標記清除算法、復制算法、標記整理算法、分代回收


面試官: 你能詳細聊一下分代回收嗎?

候選人:

關于分代回收是這樣的

在java8時,堆被分為了兩份:新生代和老年代,它們默認空間占用比例是1:2

對于新生代,內部又被分為了三個區域。Eden區,S0區,S1區默認空間占用比例是8:1:1

具體的工作機制是有些情況:

  1. 當創建一個對象的時候,那么這個對象會被分配在新生代的Eden區。當Eden區要滿了時候,觸發YoungGC。

  2. 當進行YoungGC后,此時在Eden區存活的對象被移動到S0區,并且當前對象的年齡會加1,清空Eden區。

  3. 當再一次觸發YoungGC的時候,會把Eden區中存活下來的對象和S0中的對象,移動到S1區中,這些對象的年齡會加1,清空Eden區和S0區。

  4. 當再一次觸發YoungGC的時候,會把Eden區中存活下來的對象和S1中的對象,移動到S0區中,這些對象的年齡會加1,清空Eden區和S1區。

  5. 對象的年齡達到了某一個限定的值(默認15歲 ),那么這個對象就會進入到老年代中。

當然也有特殊情況,如果進入Eden區的是一個大對象,在觸發YoungGC的時候,會直接存放到老年代

當老年代滿了之后,觸發FullGCFullGC同時回收新生代和老年代,當前只會存在一個FullGC的線程進行執行,其他的線程全部會被掛起。 我們在程序中要盡量避免FullGC的出現。


面試官:講一下新生代、老年代、永久代的區別?

候選人:

嗯!是這樣的,簡單說就是

  • 新生代主要用來存放新生的對象。

  • 老年代主要存放應用中生命周期長的內存對象。

  • 永久代指的是永久保存區域。主要存放Class和Meta(元數據)的信息。在Java8中,永久代已經被移除,取而代之的是一個稱之為“元數據區”(元空間)的區域。元空間和永久代類似,不過元空間與永久代之間最大的區別在于:元空間并不在虛擬機中,而是使用本地內存。因此,默認情況下,元空間的大小僅受本地內存的限制。


面試官:說一下 JVM 有哪些垃圾回收器?

候選人:

在jvm中,實現了多種垃圾收集器,包括:串行垃圾收集器、并行垃圾收集器(JDK8默認)、CMS(并發)垃圾收集器、G1垃圾收集器(JDK9默認)


面試官:Minor GC、Major GC、Full GC是什么

候選人:

嗯,其實它們指的是不同代之間的垃圾回收

  • Minor GC 發生在新生代的垃圾回收,暫停時間短

  • Major GC 老年代區域的垃圾回收,老年代空間不足時,會先嘗試觸發Minor GC。Minor GC之后空間還不足,則會觸發Major GC,Major GC速度比較慢,暫停時間長

  • Full GC 新生代 + 老年代完整垃圾回收,暫停時間長,應盡力避免

四、JVM實踐(調優)

面試官:JVM 調優的參數可以在哪里設置參數值?

候選人:

我們當時的項目是springboot項目,可以在項目啟動的時候,java -jar中加入參數就行了


面試官:用的 JVM 調優的參數都有哪些?

候選人:

  • 嗯,這些參數是比較多的

  • 我記得當時我們設置過堆的大小,像-Xms和-Xmx

  • 還有就是可以設置年輕代中Eden區和兩個Survivor區的大小比例

  • 還有就是可以設置使用哪種垃圾回收器等等。具體的指令還真記不太清楚。


面試官:嗯,好的,你們平時調試 JVM都用了哪些工具呢?

候選人:

嗯,我們一般都是使用jdk自帶的一些工具,比如

  • jps 輸出JVM中運行的進程狀態信息

  • jstack查看java進程內線程的堆棧信息。

  • jmap 用于生成堆轉存快照

  • jstat用于JVM統計監測工具

還有一些可視化工具,像jconsole和VisualVM等


面試官:假如項目中產生了java內存泄露,你說一下你的排查思路?

候選人:

嗯,這個我在之前項目排查過

  • 第一呢可以通過jmap指定打印他的內存快照 dump文件,不過有的情況打印不了,我們會設置vm參數讓程序自動生成dump文件

  • 第二,可以通過工具去分析 dump文件,jdk自帶的VisualVM就可以分析

  • 第三,通過查看堆信息的情況,可以大概定位內存溢出是哪行代碼出了問題

  • 第四,找到對應的代碼,通過閱讀上下文的情況,進行修復即可


面試官:好的,那現在再來說一種情況,就是說服務器CPU持續飆高,你的排查方案與思路?

候選人:

嗯,我思考一下~~

可以這么做~~

  • 第一可以使用使用top命令查看占用cpu的情況

  • 第二通過top命令查看后,可以查看是哪一個進程占用cpu較高,記錄這個進程id

  • 第三可以通過ps 查看當前進程中的線程信息,看看哪個線程的cpu占用較高

  • 第四可以jstack命令打印進行的id,找到這個線程,就可以進一步定位問題代碼的行號

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/12484.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/12484.shtml
英文地址,請注明出處:http://en.pswp.cn/web/12484.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【十大排序算法】----C語言版插入排序(詳細圖解)

目錄 一:插入排序——原理 二:插入排序——分析 三:插入排序——實現 四:插入排序——效率 一:插入排序——原理 插入排序的原理和基本思想:把待排序的記錄按其關鍵碼值的大小逐個插入到一個已經排好序…

無需重啟 NGINX 開源版即可實現 SSL/TLS 證書輪換

原文作者:Maxim Ivanitskiy of F5 原文鏈接:無需重啟 NGINX 開源版即可實現 SSL/TLS 證書輪換 轉載來源:NGINX 開源社區 NGINX 唯一中文官方社區 ,盡在 nginx.org.cn 在高性能 Web 服務器領域,NGINX 是一個廣受歡迎的…

Django使用

一、根目錄下安裝 pip install django 二、創建djiango項目 django-admin startproject 項目名稱 三、創建app python manage.py startapp app名稱 四、啟動 python manage.py runserver 五、編寫URL與視圖關系,相對路徑 1、manage.py(見資源綁定…

mysql 8 創建用戶并賦予改用戶指定數據庫權限

一、使用客戶端工具登錄mysql 二、創建用戶 -- 低版本數據庫 create user 用戶名% identified by 密碼; -- 高版本數據庫 create user 用戶名% identified with mysql_native_password by 密碼; -- 示例1: create user test% identified with mysql_native_passwor…

apt和apt-get有什么區別

2024年5月15日,周三上午 apt 和 apt-get 都是 Debian 及其衍生版(如 Ubuntu)中用于軟件包管理的工具,但它們之間存在一些差異。 功能和目的: apt 是 apt-get 的改進版本,提供了更簡潔和更直觀的命令選項。…

多元化、高辨識顯示丨基于G32A1445的汽車尾燈解決方案

由剎車燈、倒車燈、轉向燈、霧燈等組成的汽車尾燈,既能在光線低暗時發出照明信息,也可向周圍環境傳遞車輛的行駛狀態與意圖信號,對于行車安全起著至關重要的作用。與傳統尾燈相比,貫穿式汽車尾燈更加醒目、美觀、安全,…

CSS2(一):CSS選擇器

文章目錄 1、CSS基礎1.1 CSS簡介1.2 CSS編寫位置1.2.1 行內樣式1.2.2 內部樣式1.2.3 外部樣式1.2.4 樣式優先級 1.2.5 CSS代碼風格 2、CSS選擇器2.1、基本選擇器2.1.1 通配選擇器2.1.2 元素選擇器2.1.3 類選擇器2.1.4 ID選擇器2.1.5 總結 2.2、CSS復合選擇器2.2.1 交集選擇器2.…

海外媒體宣發:新加坡.馬來西亞如何在海外媒體投放新聞通稿-大舍傳媒

導言 隨著全球化的進程加速,海外市場對于企業的發展越來越重要。而在海外媒體上宣傳企業的新聞通稿,成為了拓展海外市場和提升企業知名度的重要手段之一。本文將介紹大舍傳媒對于如何在海外媒體上投放新聞通稿的經驗和策略。 準備工作:了解…

Hive 特殊的數據類型 Array、Map、Struct

Array 數組類型,存儲數據類型一致的列表數據。 我們可以使用 array 方法來創建一個數組,如下所示: select array(1,2,3,4,5);如果其中的數據類型不一致,那么它會轉換成統一的數據類型(前提是能夠進行轉換&#xff0…

力扣HOT100 - 322. 零錢兌換

解題思路&#xff1a; 動態規劃 class Solution {public int coinChange(int[] coins, int amount) {int[] dp new int[amount 1];Arrays.fill(dp, amount 1);dp[0] 0;for (int i 1; i < amount; i) {for (int j 0; j < coins.length; j) {if (coins[j] < i) …

word內容wxml轉化html標簽對照表

1. 標簽 w:document document 文檔w:bodybody文檔的主體w:sectPrsection——w:pp/div段落w:rspan行內元素w:ttext文本w:tbltable表格w:trtr表格行w:tctd單元格w:brbr換行w:hyperlinka超鏈接w:roundrectdiv/canvas塊w:pictimg圖片w:inlinespan行元素w:oMathmath公式w:subsub下標…

寵物管理系統帶萬字文檔

文章目錄 寵物管理系統一、項目演示二、項目介紹三、19000字論文參考四、部分功能截圖五、部分代碼展示六、底部獲取項目源碼和萬字論文參考&#xff08;9.9&#xffe5;帶走&#xff09; 寵物管理系統 一、項目演示 寵物管理系統 二、項目介紹 基于springbootvue的前后端分離…

如何讓Linux系統崩潰?

如何使 Linux 系統崩潰 警告 下面的代碼行是 Bash shell 的一個簡短而甜蜜的 fork 炸彈。分叉炸彈之所以有效&#xff0c;是因為它能夠產生無限數量的進程。最終&#xff0c;Linux無法處理所有這些&#xff0c;并且會崩潰。 fork 炸彈的一大優點是你不需要 root 權限即可執行它…

Vu2之使用provide與inject調用方法案例

Vu2之使用provide與inject調用方法案例 文章目錄 Vu2之使用provide與inject調用方法案例1. 祖先組件使用provide提供方法2. 后代組件使用inject注入并調用方法 在Vue 2中&#xff0c;provide和inject是用于在組件之間傳遞數據的一種高級技術。雖然它們通常用于傳遞數據&#xf…

【scikit-learn001】邏輯回歸(Logistic Regression)ML模型實戰及經驗總結(更新中)

1.一直以來想寫下基于scikit-learn訓練AI算法的系列文章&#xff0c;作為較火的機器學習框架&#xff0c;也是日常項目開發中常用的一款工具&#xff0c;最近剛好擠時間梳理、總結下這塊兒的知識體系。 2.熟悉、梳理、總結下scikit-learn框架邏輯回歸&#xff08;Logistic Regr…

新串口通道打通紀實

在計算機系統中&#xff0c;串口是“古老”的通信方式&#xff0c;和它同時代的“并口”通信方式已經消失了。但它仍然頑強的存活著&#xff0c;主要原因是在開發和調試底層軟件時還經常用到串口。 正因為有這樣的需求&#xff0c;幽蘭代碼本是支持串口的&#xff0c;而且有兩種…

vue中父子組件如何相互調用方法

Vue 中父子組件如何相互調用方法 在 Vue 中&#xff0c;父子組件可以通過以下方法相互調用方法&#xff1a; 父組件調用子組件方法 通過 props: 父組件向子組件傳遞一個 prop&#xff0c;該 prop 是一個函數&#xff0c;子組件可以調用它來觸發父組件的方法。通過 refs: 父組…

【現代C++】概念的使用

現代C&#xff08;特別是C20及以后的版本&#xff09;引入了概念&#xff08;Concepts&#xff09;&#xff0c;這是一種指定模板參數必須滿足的約束的方式。概念使得模板代碼更清晰&#xff0c;更容易理解和使用&#xff0c;并且能在編譯時提供更好的錯誤信息。以下是C概念的關…

UStaticMesh幾何數據相關(UE5.2)

UStaticMesh相關類圖 UStaticMesh的數據構成 UStaticMesh的FStaticMeshSourceModel UStaticMesh的Mesh幾何元數據來自于FStaticMeshSourceModel&#xff0c; 一級Lod就存在一個FStaticMeshSourceModel. FStaticMeshSourceModel幾何數據大致包含以下幾類: Vertex(點), VertexI…