八股文——JVM

?1. JVM組成

1.1 JVM由哪些部分組成?運行流程?

  • Java Virtual Machine:Java 虛擬機,Java程序的運行環境(java二進制字節碼的運行環境)
  • 好處:一次編寫,到處運行;自動內存管理,垃圾回收機制
  • 程序運行之前,需要先通過編譯器將 Java 源代碼文件編譯成 Java 字節碼文件;
  • 程序運行時,JVM 會對字節碼文件進行逐行解釋,翻譯成機器碼指令,并交給對應的操作系統去執行。

?

?

  • 好處:一次編寫,到處運行;自動內存管理,垃圾回收機制

  • JVM? <--->?操作系統(windows、linux)<--->?計算機硬件(cpu、內存條)
    java跨平臺是因JVM屏蔽了操作系統的差異,真正運行代碼的不是操作系統

?

?

  • JVM 主要由四個部分組成: 運行流程:
  • Java 編譯器(javac)將 Java 代碼轉換為字節碼(.class 文件)
  • 1. 類加載器(ClassLoader)
  • 負責加載 .class 文件,將 Java 字節碼加載到內存中,并交給 JVM 執行
  • 2. 運行時數據區(Runtime Data Area)
  • 管理JVM使用的內存。主要包括:
  • 方法區(Method Area):存儲類的元數據、常量、靜態變量等。
  • 堆(Heap):存儲所有對象和數組,垃圾回收器主要回收堆中的對象。
  • 棧(Stack):每個線程都有一個棧,用于存儲局部變量、方法調用等信息。
  • 程序計數器(PC Register):每個線程有一個程序計數器,指示當前線程正在執行的字節碼指令地址。
  • 本地方法棧(Native Method Stack):支持本地方法的調用(通過 JNI)。
  • 其中方法區和堆是線程共享的,虛擬機棧、本地方法棧和程序計數器是線程私有的。
  • 3. 執行引擎(Execution Engine)
  • 負責執行字節碼,包含:
  • 解釋器:逐條解釋執行字節碼。
  • JIT 編譯器:將熱點代碼編譯為機器碼,提高執行效率。
  • 垃圾回收器:回收堆中的不再使用的對象,釋放內存。
  • 4. 本地庫接口(Native Method Library)
  • 允許 Java 程序通過 java本地接口JNI(Java Native Interface)調用本地方法(如 C/C++ 編寫的代碼),與底層系統或硬件交互。

?1.2 什么是程序計數器

  • 程序計數器:線程私有的,每個線程一份,內部保存字節碼的行號。用于記錄正在執行的字節碼指令的地址。
  • 每個線程都有自己的程序計數器,確保線程切換時能夠繼續執行未完成的任務。

1.3 你能給我詳細的介紹java堆嗎?

  • Java堆是 JVM 中用于存儲所有對象和數組的內存區域。線程共享的區域。當堆中沒有內存空間可分配給實例,也無法再擴展時,則拋出OutOfMemoryError異常。
  • 它被分為:
  • 年輕代(存儲新創建的對象),被劃分為三部分:
  • Eden區:大多數新對象的分配區域;
  • S0 和 S1(兩個大小嚴格相同的Survivor區):Eden 空間經過 GC 后存活下來的對象會被移到其中一個 Survivor 區域;
  • 老年代:在經過幾次垃圾收集后,任然存活于Survivor的對象將被移動到老年代區間。
  • 永久代:JDK 7 及之前,JVM 的方法區(也稱永久代),保存的類信息、靜態變量、常量、編譯后的代碼;
  • 元空間:JDK 8 及之后,永久代被 Metaspace(元空間)取代,移除了永久代,把數據存儲到了本地內存的元空間中,且其大小不再受 JVM 堆的限制,防止內存溢出。

1.4 什么是虛擬機棧

Java Virtual machine Stacks (java 虛擬機棧)

  • 每個線程在 JVM 中私有的一塊內存區域,稱為虛擬機棧,先進后出,用于存儲方法的局部變量和方法調用信息;
  • 每個棧由多個棧幀(frame)組成,當線程執行方法時,為該方法分配一個棧幀(Stack Frame);
  • 每個線程只能有一個活動棧幀,對應著當前正在執行的那個方法;

垃圾回收是否涉及棧內存?
  • 垃圾回收主要指就是堆內存
  • 棧內存中不會有垃圾回收的概念,因為棧內存是由 JVM 自動管理的,方法執行完成時,棧幀彈棧,內存就會釋放;
棧內存分配越大越好嗎?
  • 未必,默認的棧內存通常為1024k;
  • 棧內存過大會導致線程數變少,例如,機器總內存為512m,目前能活動的線程數則為512個,如果把棧內存改為2048k,那么能活動的線程數減半;

方法內的局部變量是否線程安全?

  • 方法內的局部變量 本身是線程安全的,因為它們存儲在每個線程獨立的棧中,不會被其他線程共享。
  • 但如果局部變量是引用類型,并且該引用指向的對象逃離了方法作用范圍(例如被返回或傳遞到外部),則需要考慮該對象的線程安全性。
  • 如果對象是可變的,并且被多個線程訪問,可能會引發線程安全問題。
棧內存溢出情況(StackOverflowError)
  • 棧幀過多導致棧內存溢出;
    典型問題:遞歸調用會在棧中創建新的棧幀,如果遞歸深度過大,可能會導致棧空間耗盡,從而拋出

  • 棧幀過大導致棧內存溢出

堆棧的區別是什么?

  • 棧內存用來存儲局部變量和方法調用,但堆內存是用來存儲Java對象和數組的。
  • 堆會GC垃圾回收,而棧不會;
  • 棧內存是線程私有的,而堆內存是線程共有的;
  • 兩者異常錯誤不同,但如果棧內存或者堆內存不足都會拋出異常
  • 棧空間不足:java.lang.StackOverFlowError
  • 堆空間不足:java.lang.OutOfMemoryError

1.5 說一下JVM運行時數據區

JVM 運行時數據區包括方法區、堆、棧、程序計數器和本地方法棧。

  • 方法區存儲類的元數據、常量池、靜態變量和 JIT 編譯后的代碼。
  • 類的結構信息:每個類的信息,如類名、父類名、接口、方法、字段的名稱和描述等。常量池:存儲常量值,如字符串常量、類常量等。靜態變量:屬于類的變量,而不是某個實例的變量。JIT編譯后的代碼是指 Jvm在運行時將熱點代碼從字節碼編譯為本地機器代碼。方法區在 JDK 7 之前被稱為 "永久代",從 JDK 8 開始,永久代被移除,改為使用元空間
  • 堆是 JVM 中最大的內存區域,負責存儲所有的對象實例和數組,并進行垃圾回收。
  • 棧存儲每個線程的局部變量、方法調用信息和返回地址等。
  • 堆和棧是線程共享和線程私有的區域。
  • 程序計數器是每個線程私有的,用于存儲當前線程正在執行的字節碼指令的地址。
  • 本地方法棧支持 JNI 本地方法調用,線程私有。
  • 專門為本地方法調用而設計。它用于執行本地代碼時所需的棧空間。

1.6? 能不能介紹一下方法區

  • 方法區 是 JVM 運行時數據區的一部分,主要用于存儲類的信息、常量、靜態變量以及 JIT 編譯后的代碼。
  • 在 JDK 7 之前,這部分內存稱為永久代(PermGen),而在 JDK 8 以后,永久代被移除,取而代之的是元空間(Metaspace),它位于本地內存中,不再受堆內存限制。
  • 虛擬機啟動的時候創建,關閉虛擬機時釋放。
  • 方法區的內存由 JVM 管理,并在類卸載時進行垃圾回收。
  • 如果方法區域中的內存無法滿足分配請求,則會拋出OutOfMemoryError: Metaspac

1.7 介紹一下運行時常量池?

常量池
  • 可以看作是一張表,虛擬機指令根據這張常量表找到要執行的類名、方法名、參數類型、字面量等信息

運行時常量池
  • 常量池是?.class?文件中的,當該類被加載,它的常量池信息就會放入運行時常量池,并把里面的符號地址變為真實地址

1.8 你聽過直接內存嗎?

  • 它不受 JVM 內存回收管理,是虛擬機的系統內存;
  • 常見于在 NIO 中使用直接內存,不需要在堆中開辟空間進行數據的拷貝,jvm可以直接操作直接內存,從而使數據讀寫傳輸更快。但分配回收成本較高。
  • 使用傳統的IO的時間要比NIO操作的時間長了很多,也就說NIO的讀性能更好。
  • 這個是跟我們的JVM的直接內存是有一定關系,如下圖,傳統阻塞IO的數據傳輸流程和NIO傳輸數據的流程。

2. 類加載器

2.1 什么是類加載器,類加載器有哪些?

  • JVM只會運行二進制文件,而類加載器(ClassLoader)的主要作用就是將.class字節碼文件加載到JVM內存,生成對應的Class對象,供程序使用。

  • 啟動類加載器(BootStrap ClassLoader):
  • 該類并不繼承ClassLoader類,其是由C++編寫實現。用于加載JAVA_HOME/jre/lib目錄下的類庫。
  • 擴展類加載器(ExtClassLoader):
  • 該類是ClassLoader的子類,主要加載JAVA_HOME/jre/lib/ext目錄中的類庫。
  • 應用類加載器(AppClassLoader):
  • 該類是ClassLoader的子類,主要用于加載classPath下的類,也就是加載開發者自己編寫的Java類。
  • 自定義類加載器:
  • 開發者自定義類繼承ClassLoader,實現自定義類加載規則。

類加載器的體系并不是“繼承”體系,而是委派體系,類加載器首先會到自己的parent中查找類或者資源,如果找不到才會到自己本地查找。類加載器的委托行為動機是為了避免相同的類被加載多次

2.2 什么是雙親委派模型?

  • 雙親委派模型要求類加載器在加載某一個類時,先委托父加載器嘗試加載。
  • 如果父加載器可以完成類加載任務,就返回成功;
  • 只有父加載器無法加載時,子加載器才會加載。

2.3 JVM為什么采用雙親委派機制?

  • 避免類的重復加載:父加載器加載的類,子加載器無需重復加載。

  • 保證核心類庫的安全性:為了安全,保證類庫API不會被修改。如?java.lang包下的類只能由?啟動類加載器Bootstrap ClassLoader 加載,防止被篡改。

2.4 說一下類的生命周期

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

2.5 說一下類裝載的執行過程?

類裝載過程包括三個階段:載入、連接和初始化,連接細分為 驗證、準備、解析,這是標準的 JVM 類裝載流程。

  1. 加載(Loading):通過類加載器找到 .class 文件讀取到內存,生成 Class 對象。
  2. 連接(Linking):

驗證:檢查字節碼是否合法,防止惡意代碼破壞 JVM;
準備:為類的靜態變量分配內存并設置默認初始值,但不執行賦值邏輯;
解析:將常量池中的 符號引用(如類名、方法名)轉為 直接引用(內存地址)。

  1. 初始化(Initialization):執行類的靜態代碼塊和靜態變量賦值。

在準備階段,靜態變量已經被賦過默認初始值了,在初始化階段,靜態變量將被賦值為代碼期望賦的值。比如說 static int a = 1;,在準備階段,a 的值為 0,在初始化階段,a 的值為 1

類裝載完成后的階段:加載完成后,類進入‘使用階段’。當 Class 對象不再被引用時,可能觸發‘卸載’。

  • 使用:JVM 通過 Class 對象創建實例、調用方法,進入正常運行階段。
  • 卸載:當 Class 對象不再被引用時,由 GC 回收,但 JVM 核心類(如 java.lang.*)不會被卸載。

3. 垃圾回收

3.1 簡述java垃圾回收機制?(GC是什么?為什么要GC)

  • GC(Garbage Collection,垃圾回收)是 Java 中自動管理內存的機制,負責回收不再使用的對象,以釋放內存空間。
  • 垃圾回收是 Java 程序員不需要顯式管理內存的一大優勢,它由 JVM 自動進行。

GC 的主要目的是:
自動管理內存:程序運行過程中會創建大量的對象,但一些對象在使用完后不再被引用。手動管理這些對象的內存釋放非常繁瑣且容易出錯;
防止內存泄漏:如果不及時釋放無用對象的內存,系統的可用內存會越來越少,最終可能導致 OutOfMemoryError;
避免內存溢出:GC 機制能夠保證內存不會因為長期積累未回收的對象而耗盡。

3.2?對象什么時候可以被垃圾器回收?

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

如果要定位什么是垃圾,有兩種方式來確定,
1. 引用計數法:通過計數引用的數量,當引用為 0 時回收。但不能處理循環引用
這種方法通過給每個對象維護一個引用計數器。當有一個新的引用指向該對象時,引用計數加 1;當引用離開時,計數減 1。
2. 可達性分析算法:通過檢查對象是否從根對象可達,無法訪問的對象可以回收。是 Java 使用的主要方法。
根對象是那些肯定不能當做垃圾回收的對象,就可以當做根對象
根對象包含:虛擬機棧中的局部變量;靜態變量;活動線程的引用;JNI 引用的對象。

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

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

相關文章

在Pnetlab6上繞過TPM、安全啟動和 RAM 檢查安裝windows 11筆記

筆者本次安裝的windows11的鏡像為: zh-cn_windows_11_enterprise_ltsc_2024_x64_dvd_cff9cd2d.iso 1、創建鏡像目錄并上傳iso文件 mkdir /opt/unetlab/addons/qemu/win-win11x64-2024-LTSC //目錄名稱務必按照官方文檔格式,否則無法識別 目錄創建完成后,將.iso格式鏡像上…

PCL點云庫入門(第18講)——PCL庫點云特征之3DSC特征描述3D shape context descriptor

一、3DSC&#xff08;3D Shape Context&#xff09;特征算法原理 1. 背景 3DSC 是一種描述三維點云局部形狀的特征描述子&#xff0c;受二維 Shape Context 的啟發。它用于捕捉點云某一點局部的幾何分布信息&#xff0c;對點云配準、識別等任務非常有效。 2. 基本思想 3DSC…

SpringBoot+Mysql校園跑腿服務平臺系統源碼

&#x1f497;博主介紹&#x1f497;&#xff1a;?在職Java研發工程師、專注于程序設計、源碼分享、技術交流、專注于Java技術領域和畢業設計? 溫馨提示&#xff1a;文末有 CSDN 平臺官方提供的老師 Wechat / QQ 名片 :) Java精品實戰案例《700套》 2025最新畢業設計選題推薦…

分庫分表的取舍

文章目錄 大數據量下采用**水平分表**的缺點**1. 跨表查詢復雜性與性能下降****2. 數據分布不均衡****3. 分布式事務與一致性問題****4. 擴展性受限****5. 查詢條件限制與索引管理復雜****6. 數據遷移與維護成本高****7. 業務邏輯復雜度增加****總結** shardingJdbc分片策略**1…

Vue3解決“找不到模塊@/components/xxx.vue或其相應的類型聲明ts文件(2307)”

問題 1&#xff1a;如果沒有這個env.d.ts文件&#xff0c;就新建 declare module "*.vue" {import { DefineComponent } from "vue";const component: DefineComponent<{}, {}, any>;export default component; }2&#xff1a;如果有tsconfig.json文…

計算機視覺與深度學習 | 基于MATLAB的圖像特征提取與匹配算法總結

基于MATLAB的圖像特征提取與匹配算法全面指南 圖像特征提取與匹配 基于MATLAB的圖像特征提取與匹配算法全面指南一、圖像特征提取基礎特征類型分類二、點特征提取算法1. Harris角點檢測2. SIFT (尺度不變特征變換)3. SURF (加速魯棒特征)4. FAST角點檢測5. ORB (Oriented FAST …

如何通過API接口獲取淘寶商品列表?操作詳解

一、準備工作 注冊開發者賬號 訪問淘寶開放平臺官網/萬邦開放平臺&#xff0c;完成企業開發者認證&#xff08;個人賬號權限受限&#xff09;&#xff0c;使用已有淘寶賬號可直接登錄。創建應用并填寫基本信息&#xff08;如應用名稱、類型等&#xff09;&#xff0c;系統生成A…

大數據驅動企業決策智能化的路徑與實踐

&#x1f4dd;個人主頁&#x1f339;&#xff1a;慌ZHANG-CSDN博客 &#x1f339;&#x1f339;期待您的關注 &#x1f339;&#x1f339; 一、引言&#xff1a;數據驅動的企業競爭力重構 在這個瞬息萬變的商業時代&#xff0c;“快者勝”的競爭邏輯愈發明顯。企業如何在復雜環…

DataGridView關閉默認第一列及表頭居中設置

1、關閉默認第一列 如上圖所示&#xff0c;C#和VB.net中的DataGridView控件都是有一個默認的第一列&#xff08;雖然是空白&#xff09;的&#xff0c;如何關閉這個默認列呢&#xff1f; 把“RowHeadersVisible”的值設置成“false”就可以了&#xff1a; 2、表頭居中顯示 如上…

nodejs express 打包部署

當前文件路徑 webpack.config.js const path require(path); module.exports {entry: ./app.js, // Express 入口文件target: node, // 指定 Node.js 環境output: {path: path.resolve(__dirname, dist),filename: bundle.js},mode: production };打包命令 npx webpac…

CentOS 7 修改為靜態 IP 地址完整指南

在企業網絡環境中,服務器通常需要配置靜態 IP 地址以確保網絡連接的穩定性和可管理性。以下是使用 NetworkManager 工具在 CentOS 7 系統中將動態 IP 配置修改為靜態 IP 的完整指南: 一、檢查當前網絡配置 查看網絡連接狀態: 使用 nmcli connection show 命令列出所有網絡連…

微信小程序動態組件加載的應用場景與實現方式

動態組件加載的應用場景與實現方式 你提供的代碼展示了微信小程序中動態加載組件的方法&#xff0c;但這種方式在實際開發中需要注意使用場景和實現細節。下面我來詳細說明如何應用&#xff1a; 應用場景 按需加載組件&#xff1a;在某些條件滿足時才加載組件動態配置組件&a…

學習記錄: 使用react-router-dom

假設有一個vite創建的react項目,先npm install react-router-dom. 在app中: import { RouterProvider, createBrowserRouter } from "react-router-dom"; import Login from "./comm/Login"; import Home from "./comm/Home"; import TotalMan…

Angular中Webpack與ngx-build-plus 淺學

Webpack 在 Angular 中的概念 Webpack 是一個模塊打包工具&#xff0c;用于將多個模塊和資源打包成一個或多個文件。在 Angular 項目中&#xff0c;Webpack 負責將 TypeScript、HTML、CSS 等文件打包成瀏覽器可以理解的 JavaScript 文件。Angular CLI 默認使用 Webpack 進行項目…

java中word快速轉pdf

java中word快速轉pdf 網上其他方法轉pdf要不轉的太慢&#xff0c;要不就是損失格式&#xff0c;故而留下此方法留作備用。 文章目錄 java中word快速轉pdf一、依賴二、依賴包三、代碼 一、依賴 <dependency><groupId>com.aspose</groupId><artifactId>…

Maven 概述、安裝、配置、倉庫、私服詳解

目錄 1、Maven 概述 1.1 Maven 的定義 1.2 Maven 解決的問題 1.3 Maven 的核心特性與優勢 2、Maven 安裝 2.1 下載 Maven 2.2 安裝配置 Maven 2.3 測試安裝 2.4 修改 Maven 本地倉庫的默認路徑 3、Maven 配置 3.1 配置本地倉庫 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…

Unity使用代碼分析Roslyn Analyzers

一、創建項目&#xff08;注意這里不要選netstandard2.1會有報錯&#xff09; 二、NuGet上安裝Microsoft.CodeAnalysis.CSharp 三、實現[Partial]特性標注的類&#xff0c;結構體&#xff0c;record必須要partial關鍵字修飾 需要繼承DiagnosticAnalyzer 注意一定要加特性Diagn…

knife4j:4.3.0 default-flat-param-object: true 沒有生效

Get 方式請求 前端接口文檔中的鍵值對方式&#xff08;get&#xff09;發送對象參數&#xff0c;將對象請求參數展開

C++.OpenGL (15/64)Assimp(Open Asset Import Library)

Assimp(Open Asset Import Library) 3D模型加載核心流程 #mermaid-svg-cKmTZDxPpROr7ly1 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-cKmTZDxPpROr7ly1 .error-icon{fill:#552222;}#mermaid-svg-cKmTZDxPpROr…

課堂筆記:吳恩達的AI課(AI FOR EVERYONE)-第一周part2 人工智能術語人工智能公司應該怎么做

人工智能術語&人工智能公司應該怎么做 一、人工智能術語 1.機器學習&#xff1a; 讓電腦能夠不用開發軟件&#xff0c;而自主獲取某種能力的研究領域。 2.數據科學&#xff1a; 從數據中提取知識和見解的科學&#xff1b; 3.深度學習&#xff1a; 度學習是一種機器…