JVM 面經

1、什么是 JVM?

JVM 就是 Java 虛擬機,它是 Java 實現跨平臺的基石。程序運行之前,需要先通過編譯器將 Java 源代碼文件編譯成 Java 字節碼文件;程序運行時,JVM 會對字節碼文件進行逐行解釋,翻譯成機器碼指令,交給對應的操作系統執行。這樣就實現了 Java 一次編譯,處處運行的特性。
在這里插入圖片描述

1.1 說說 JVM 的其他特性?

  1. JVM 可以自動管理內存,通過垃圾回收器回收不再使用的對象并釋放內存空間。
  2. JVM 包含一個即時編譯器 JIT,它可以在運行時將熱點代碼緩存到 codeCache 中,下次執行的時候不用再一行一行的解釋,而是直接執行緩存后的機器碼,執行效率會大幅提高。
  3. 任何可以通過 Java 編譯的語言,比如說 Groovy、Kotlin、Scala 等,都可以在 JVM 上運行。

1.2 為什么要學習 JVM ?

學習 JVM 可以幫助我們開發者更好地優化程序性能、避免內存問題。比如:了解 JVM 的內存模型和垃圾回收機制,可以幫助我們更合理地配置內存、減少 GC 停頓。掌握 JVM 的類加載機制可以幫助我們排查類加載沖突或異常。JVM 還提供了很多調試和監控工具,可以幫助我們分析內存和線程的使用情況,從而解決內存溢出內存泄露等問題。

2、說說 JVM 的組織架構

JVM 大致可以劃分為三個部分:類加載器、運行時數據區和執行引擎。
在這里插入圖片描述

  1. 類加載器:負責從文件系統、網絡或其他來源加載 Class 文件,將 Class 文件中的二進制數據讀入到內存當中。
  2. 運行時數據區:JVM 在執行 Java 程序時,需要在內存中分配空間來處理各種數據,這些內存區域按照 Java 虛擬機規范可以劃分為方法區、堆、虛擬機棧、本地方法棧和程序計數器。
  3. 執行引擎:JVM 的心臟,負責執行字節碼。它包括解釋器、JIT 編譯器和垃圾回收器。

3、能說一下 JVM 的內存區域嗎?

按照 Java 虛擬機規范,JVM 的內存區域可以細分為方法區、堆、虛擬機棧、本地方法棧和程序計數器。其中方法區和堆是線程共享的,虛擬機棧、本地方法棧和程序計數器是線程私有的。

3.1 介紹一下方法區?

方法區并不真實存在,是 Java 虛擬機規范中的一個邏輯概念,用于存儲已被 JVM 加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼緩存等。在 HotSpot 虛擬機中,方法區的實現稱為永久代 PermGen,但在 Java 8 及之后的版本中,已經被元空間 Metaspace 所替代。

3.2 介紹一下 Java 堆?

堆是 JVM 中最大的一塊內存區域,被所有線程共享,在 JVM 啟動時創建,主要用來存儲 new 出來的對象。Java 中幾乎所有的對象都會在堆中分配,堆也是垃圾收集器管理的目標區域。
在這里插入圖片描述
從內存回收的角度來看,由于垃圾收集器大部分都是基于分代收集理論設計的,所以堆又被細分為新生代、老年代、Eden空間、From Survivor空間、To Survivor空間等。
在這里插入圖片描述
從 JDK 7 開始,JVM 默認開啟了逃逸分析,意味著如果某些方法中的對象引用沒有被返回或者沒有在方法體外使用,也就是未逃逸出去,那么對象可以直接在棧上分配內存。

3.3 介紹一下 Java 虛擬機棧?

Java 虛擬機棧的生命周期與線程相同。當線程執行一個方法時,會創建一個對應的棧幀,用于存儲局部變量表、操作數棧、動態鏈接、方法出口等信息,然后棧幀會被壓入虛擬機棧中。當方法執行完畢后,棧幀會從虛擬機棧中移除。

3.4 介紹一下本地方法棧?

本地方法棧與虛擬機棧相似,區別在于虛擬機棧是為 JVM 執行 Java 編寫的方法服務的,而本地方法棧是為 Java 調用本地 native 方法服務的,通常由 C/C++ 編寫。

3.5 介紹一下本地方法棧的運行場景?

當 Java 應用需要與操作系統底層或硬件交互時,通常會用到本地方法棧。比如調用操作系統的特定功能,如內存管理、文件操作、系統時間、系統調用等。
在這里插入圖片描述
在這里插入圖片描述

3.6 native 方法解釋一下?

native 方法是在 Java 中通過 native 關鍵字聲明的,用于調用非 Java 語言,如 C/C++ 編寫的代碼。Java 可以通過 JNI,也就是 Java Native Interface 與底層系統、硬件設備、或者本地庫進行交互。

3.7 介紹一下程序計數器?

程序計數器也被稱為 PC 寄存器,是一塊較小的內存空間。它可以看作是當前線程所執行的字節碼行號指示器。

3.8 變量存在堆棧的什么位置?

對于局部變量,它存儲在當前方法棧幀中的局部變量表中。當方法執行完畢,棧幀被回收,局部變量也會被釋放。對于靜態變量來說,它存儲在 Java 虛擬機規范中的方法區中,在 Java 7 中是永久代,在 Java 8 及以后是元空間。

4、說一下 JDK 1.6、1.7、1.8 內存區域的變化?

  1. JDK 1.6 使用永久代來實現方法區。
  2. JDK 1.7 依然是永久帶,但是將字符串常量池、靜態變量存放到了堆上。
  3. JDK 1.8 直接在內存中劃出了一塊區域,叫元空間,來取代之前放在 JVM 內存中的永久代,并將運行時常量池、類常量池都移動到了元空間。

5、為什么使用元空間替代永久代?

因為永久代受到 JVM 內存大小的限制,會導致 Java 應用程序出現內存溢出的問題。

6、對象創建的過程了解嗎?

當我們使用 new 關鍵字創建一個對象時,JVM 首先會檢查 new 指令的參數是否能在常量池中定位到類的符號引用,然后檢查這個符號引用代表的類是否已被加載、解析和初始化。如果沒有,就先執行類加載。如果已經加載,JVM 會為對象分配內存完成初始化,比如數值類型的成員變量初始值是 0,布爾類型是 false,對象類型是 null。接下來,會設置對象頭,里面包含了對象是哪個類的實例、對象的哈希碼、對象的 GC 分代年齡等信息。最后,JVM 會執行構造方法 完成賦值操作,將成員變量賦值為預期的值,比如 int age = 18,這樣一個對象就創建完成了。
在這里插入圖片描述

6.1 對象的銷毀過程了解嗎?

當對象不再被任何引用指向時,就會變成垃圾。垃圾收集器會通過可達性分析算法判斷對象是否存活,如果對象不可達,就會被回收。垃圾收集器通過標記清除、標記復制、標記整理等算法來回收內存,釋放對象占用的內存空間。

7、堆內存是如何分配的?

在堆中為對象分配內存時,主要使用兩種策略:指針碰撞和空閑列表。指針碰撞適用于管理簡單、碎片化較少的內存區域,如年輕代;而空閑列表適用于內存碎片化較嚴重或對象大小差異較大的場景如老年代。
在這里插入圖片描述

  1. 指針碰撞:假設堆內存是一個連續的空間,被分為兩個部分,一部分是已經被使用的內存,另一部分是未被使用的內存。在分配內存時,Java 虛擬機會維護一個指針,指向下一個可用的內存地址,每次分配內存時,只需要將指針向后移動一段距離,如果沒有發生碰撞,就將這段內存分配給對象實例。
  2. 空閑列表:JVM 會維護一個列表,記錄堆中所有未占用的內存塊,每個內存塊都記錄有大小和地址信息。當有新的對象請求內存時,JVM 會遍歷空閑列表,尋找足夠大的空間來存放新對象。分配后,如果選中的內存塊未被完全利用,剩余的部分會作為一個新的內存塊加入到空閑列表中。

8、new 對象時,堆會發生搶占嗎?

會發生搶占。new 對象時,指針會向右移動一個對象大小的距離,假如一個線程 A 正在給 String 對象 分配內存,另一個線程 B 同時為 ArrayList 對象分配內存,兩個線程就發生了搶占。
在這里插入圖片描述

8.1 JVM 怎么解決堆內存分配的競爭問題?

為了解決堆內存分配的競爭問題,JVM 為每個線程保留了一小塊內存空間,被稱為 TLAB,也就是線程本地分配緩沖區,用于存放該線程分配的對象。當線程需要分配對象時,直接從 TLAB 中分配。只有當 TLAB 用盡或對象太大需要直接在堆中分配時,才會使用全局分配指針。
在這里插入圖片描述

9、能說一下對象的內存布局嗎?

對象的內存布局是由 Java 虛擬機規范定義的,拿我們常用的 HotSpot 來說吧。對象在內存中包括三部分:對象頭、實例數據和對齊填充。
在這里插入圖片描述

9.1 說說對象頭的作用?

對象頭是對象存儲在內存中的元信息,包含了:Mark Word、類型指針等信息。Mark Word 存儲了對象的運行時狀態信息,包括鎖、哈希值、GC 標記等。在 64 位操作系統下占 8 個字節。類型指針指向對象所屬類的元數據,也就是 Class 對象,用來支持多態、方法調用等功能。在開啟壓縮指針的情況下占 4 個字節,否則占 8 個字節。除此之外,如果對象是數組類型,還會有一個額外的數組長度字段。占 4 個字節。

9.2 實例數據了解嗎?

實例數據是對象實際的字段值,也就是成員變量的值,按照字段在類中聲明的順序存儲。JVM 會對這些數據進行對齊 / 重排,以提高內存訪問速度。

9.3 對齊填充了解嗎?

由于 JVM 的內存模型要求對象的起始地址是 8 字節對齊(64 位 JVM 中),因此對象的總大小必須是 8 字節的倍數。如果對象頭和實例數據的總長度不是 8 的倍數,JVM 會通過填充額外的字節來對齊。比如說,如果對象頭 + 實例數據 = 14 字節,則需要填充 2 個字節,使總長度變為 16 字節。

9.4 為什么非要進行 8 字節對齊呢?

因為 CPU 進行內存訪問時,一次尋址的指針大小是 8 字節,正好是 L1 緩存行的大小。如果不進行內存對齊,則可能出現跨緩存行訪問,導致額外的緩存行加載,CPU 的訪問效率就會降低。8 字節對齊,是一種以空間換時間的方案。
在這里插入圖片描述

9.5 new Object() 對象的內存大小是多少?

一般來說,目前的操作系統都是 64 位的,并且 JDK 8 中的壓縮指針是默認開啟的,因此在 64 位的 JVM 上,new Object()的大小是 16 字節(12 字節的對象頭 + 4 字節的對齊填充)。
在這里插入圖片描述
假如 MyObject 對象有三個成員變量,分別是 int、long 和 byte 類型,那么它們占用的內存大小分別是 4 字節、8 字節和 1 字節。考慮到對齊填充,MyObject 對象的總大小為 12 + 4 + 8 + 1 + 7(填充)= 32 字節。

9.6 對象的引用(類型指針)大小了解嗎?

在 64 位 JVM 上,未開啟壓縮指針時,對象引用占用 8 字節;開啟壓縮指針時,對象引用會被壓縮到 4 字節。HotSpot 虛擬機默認是開啟壓縮指針的。

10、JVM 怎么訪問對象的?

主流的方式有兩種:句柄和直接指針。句柄是通過中間的句柄表來定位對象的,優點是對象被移動時只需要修改句柄表中的指針,而不需要修改對象引用本身。直接指針是通過引用直接存儲對象的內存地址的,因為對象的實例數據和類型信息都存儲在堆中固定的內存區域。直接指針訪問的優點是訪問速度更快,因為少了一次句柄的尋址操作。缺點是如果對象在內存中移動,引用需要更新為新的地址。HotSpot 虛擬機主要使用直接指針來進行對象訪問。

11、待更新

12、

13、

14、

15、

16、

17、

18、

19、

20、

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

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

相關文章

【JavaScript】合體期功法——DOM(一)

目錄 DOMWeb API 基本概念作用和分類 什么是 DOMDOM 樹DOM 對象 獲取 DOM 元素根據 CSS 選擇器來獲取 DOM 元素選擇匹配的第一個元素選擇匹配的多個元素 其他獲取 DOM 元素方法 修改元素的內容對象.innerText 屬性對象.innerHTML 屬性案例:年會抽獎 修改元素屬性修改…

GAMMA數據處理(十)

今天向別人請教了一個問題,剛無意中搜索到了一模一樣的問題 不知道這個怎么解決... ok 解決了 有一個GAMMA的命令可轉換 但是很奇怪 完全對不上 轉換出來的行列號 不知道為啥 再試試 是因為經緯度坐標的小數點位數 de as

Java入門知識總結——章節(二)

ps:本章主要講數組、二維數組、變量 一、數組 數組是一個數據容器,可用來存儲一批同類型的數據 🔑:注意 類也可以是一個類的數組 public class Main {public static class Student {String name;int age; // 移除 unsignedint…

動態IP:網絡世界的“變色龍”如何改變你的在線體驗?

你知道嗎?有時候我覺得動態IP就像是網絡世界里的“變色龍”。它不像靜態IP那樣一成不變,而是隨時在變化,像是一個永遠在換衣服的演員。你永遠不知道它下一秒會變成什么樣子,但正是這種不確定性,讓它變得特別有趣。想象…

從24GHz到71GHz:Sivers半導體的廣泛頻率范圍5G毫米波產品解析

在5G技術的浪潮中,Sivers半導體推出了創新的毫米波無線產品,為通信行業帶來高效、可靠的解決方案。這些產品支持從24GHz到71GHz的頻率,覆蓋許可與非許可頻段,適應高速、低延遲的通信場景。 5G通信頻段的一點事兒及Sivers毫米波射頻…

aocache:AOCache 新增功能深度解析:從性能監控到靈活配置的全方位升級

最近對aocache 進行了重要升級,最新版本0.6.0增加了幾項新功能:性能分析日志,AOCache性能分析工具,切入點自定義配置,全局配置,本文詳細說明這幾項目新功能的作用和使用方式。 一、性能分析日志 需求背景…

Java EE 進階:MyBatis-plus

MyBatis-plus的介紹 MyBatis-plus是MyBatis的增強工具,在MyBatis的基礎上做出加強,只要MyBatis有的功能MyBatis-plus都有。 MyBatis-plus的上手 添加依賴 在我們創建項目的時候,我們需要添加MyBatis-plus和mysql的依賴 MyBatis-plus的依賴…

GitHub和Gitee上的一些AI項目

以下是GitHub和Gitee上的一些AI項目: GitHub上的AI項目 TensorFlow:一個端到端開源機器學習平臺,包含大量工具和庫,廣泛應用于圖像識別、自然語言處理等領域。PyTorch:由Facebook開發的開源深度學習框架,…

JavaScript網頁設計高級案例:構建交互式圖片畫廊

JavaScript網頁設計高級案例:構建交互式圖片畫廊 在現代Web開發中,交互式元素已成為提升用戶體驗的關鍵因素。本文將通過一個高級案例 - 構建交互式圖片畫廊,展示如何結合HTML和JavaScript創建引人入勝的網頁應用。這個案例不僅涵蓋了基礎的…

Linux命令大全:從入門到高效運維

適合人群:Linux新手 | 運維工程師 | 開發者 目錄 一、Linux常用命令(每天必用) 1. 文件與目錄操作 2. 文件內容查看與編輯 二、次常用命令(按需使用) 1. 系統管理與監控 2. 網絡與通信 3. 權限與用戶管理 三、…

Windows 10/11 使用 VSCode + SSH 免密遠程連接 Ubuntu 服務器(指定端口)

摘要: 本文詳細介紹如何在 Windows 系統上通過 VSCode Remote-SSH 免密登錄遠程 Ubuntu 服務器(SSH 端口 2202),避免每次輸入密碼的繁瑣操作,提高開發效率。 1. 環境準備 本地系統:Windows 10/11遠程服務…

一些需要學習的C++庫:CGAL和Eysshot

寫在前面: 從開始工作到現在,去過多家公司,多個行業, 雖然大部分時間在通信業,但也有其它的行業的工作沒有做完,但也很感興趣。每次想要研究一下時,總是想不起來。 這里寫一些信息,…

藍橋杯16天刷題計劃一一Day01

藍橋杯16天刷題計劃一一Day01(STL練習) 作者:blue 時間:2025.3.26 文章目錄 藍橋杯16天刷題計劃一一Day01(STL練習)[P1540 [NOIP 2010 提高組\] 機器翻譯 - 洛谷 (luogu.com.cn)](https://www.luogu.com.…

相對位置2d矩陣和kron運算的思考

文章目錄 1. 相對位置矩陣2d2. kron運算 1. 相對位置矩陣2d 在swin-transformer中,我們會計算每個patch之間的相對位置,那么我們看到有一連串的拉伸和相減,直接貼代碼: import torch import torch.nn as nntorch.set_printoptio…

Redis 版本演進及主要新特性

Redis 版本發布歷史 穩定版本時間線 Redis 2.6 (2012年)Redis 2.8 (2013年11月)Redis 3.0 (2015年4月) - 首次支持集群Redis 3.2 (2016年5月)Redis 4.0 (2017年7月)Redis 5.0 (2018年10月)Redis 6.0 (2020年4月)Redis 6.2 (2021年2月)Redis 7.0 (2022年4月) - 最新穩定版(截至…

HTML5 Geolocation(地理定位)學習筆記

一、HTML5 Geolocation簡介 HTML5 Geolocation(地理定位)API用于獲取用戶的地理位置信息。通過這個API,可以獲取用戶的緯度、經度、海拔等信息。由于地理定位可能涉及用戶隱私,因此只有在用戶同意的情況下,才能獲取其…

愛普生VG3225EFN壓控晶振5G基站低噪聲的解決方案

在 5G 通信網絡的高速發展中,系統噪聲的控制成為保障網絡可靠性與數據吞吐量的關鍵。愛普生 VG3225EFN 壓控晶振憑借其卓越的低噪聲特性,成為 5G 基站時鐘系統的理想選擇。通過創新的技術設計,這款晶振不僅為基站提供了穩定的時鐘基準&#x…

【問題解決】Linux安裝conda修改~/.bashrc配置文件后,root 用戶下顯示 -bash-4.2#

問題描述 在Linux安裝conda下的python環境時候,修改了~/.bashrc文件,修改完成后,再次進入服務器后,登錄時候顯示的不是正常的[rootlocalhost ~]#,而是-bash-4.2# 原因分析: 網上原因有:/root下…

機器學習knnlearn5

import numpy as np from os import listdir from sklearn.neighbors import KNeighborsClassifier as kNN# 此函數用于將一個32x32的文本文件轉換為一個1x1024的一維向量 def img2vector(filename):"""將32x32的文本文件轉換為1x1024的向量:param filename: 要…

git revert 用法實戰:撤銷一個 commit 或 merge

git revert 1 區別 ? 常規的 commit (使用 git commit 提交的 commit) ? merge commit 2 首先構建場景 master上的代碼 dev開發分支上,添加一個a標簽,并commit這次提交 切到master上,再次進行改動和提交 將de…