1. 程式人生 > 實用技巧 >JVM面試題

JVM面試題

談談對Java的理解

  • 平臺無關性
  • GC
  • 語言特性(泛型,反射,lambda等)
  • 面向物件
  • 類庫
  • 異常處理

Java的平臺無關性

Java原始碼首先被編譯成位元組碼,再由不同平臺的JVM進行解析,Java語言在不同的平臺上執行時不需要重新編譯,Java虛擬機器在執行位元組碼的時候,把位元組碼轉換成具體平臺上的機器指令。

JVM如何載入.class檔案

JVM架構圖

  • Class Loader:根據特定的格式,載入class檔案到記憶體
  • Execution Engine:對命令進行解析
  • Native Interface:融合不同開發語言的原生庫為Java所用
  • Runtime Data Area:JVM記憶體空間模型

談談反射

Java反射機制是在執行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個物件,都能夠呼叫它的任意方法和屬性;這種動態獲取資訊以及動態呼叫物件方法的功能稱為java語言的反射機制。

ClassLoader的種類

  • BootStrapClassLoader:C++編寫,載入核心庫java.*
  • ExtClassLoader:java編寫,載入擴充套件庫javax.*
  • AppClassLoader:java編寫,載入程式所在目錄(專案中的src)
  • 自定義ClassLoader:java編寫,定製化載入

雙親委派機制

參考的部落格

當某個類載入器需要載入某個.class

檔案時,它首先把這個任務委託給他的上級類載入器,遞迴這個操作,如果上級的類載入器沒有載入,自己才會去載入這個類。

作用

  1. 防止重複載入同一個.class。通過委託去向上面問一問,載入過了,就不用再載入一遍。保證資料安全。

  2. 保證核心.class不能被篡改。通過委託方式,不會去篡改核心.clas,即使篡改也不會去載入,即使載入也不會是同一個.class物件了。不同的載入器載入同一個.class也不是同一個Class物件。這樣保證了Class執行安全。

談談ClassLoader

ClassLoader在Java中有著非常重要的作用,它主要工作在Class裝載的載入階段,其主要作用是從系統外部獲得Class二進位制資料流。它是Java的核心元件,所有的Class都是由ClassLoader進行載入的,ClassLoader負責通過將Class檔案裡的二進位制資料流裝載進系統,然後交給Java虛擬機器進行連線、初始化等操作。

類載入的方式

  • 隱式載入:new
  • 顯式載入:loadClass,forName

類的裝載過程

loadClass和forName的區別

  • 使用Class.forName(className)裝載class會對相應的類進行初始化,即上圖類的裝載過程的第三步
  • 使用ClassLoader.loadClass(className)裝載class,則只會進行上圖的第一步,不會進行連結

總結

​ 一般情況下,這兩個方法效果一樣,都能裝載Class。但如果程式依賴於Class是否被初始化,就必須用Class.forName(className)了。

​ 如:jdbc中的Driver註冊時只能用Class.forName(className)

因為,Driver在static塊中會註冊自己到java.sql.DriverManager。而static塊就是在Class的初始化中被執行。所以這個地方就只能用Class.forName(className)。

JVM記憶體模型

執行緒私有部分:程式計數器、虛擬機器棧、本地方法棧

  • 程式計數器

    • 當前執行緒所執行的位元組碼行號指示器(邏輯)(多執行緒時,上下文切換,依靠程式計數器來恢復正確的執行位置)
    • 改變計數器的值來選取下一條需要執行的位元組碼指令
    • 和執行緒是一對一的關係即“執行緒私有”
    • 對Java方法計數,如果是Native方法則計數器值為Undefined
    • 不會發生記憶體洩漏
  • 虛擬機器棧

    • Java方法執行的記憶體模型
    • 包含多個棧幀
    • 區域性變量表和運算元棧
      • 區域性變量表:包含方法執行過程中的所有變數
      • 運算元棧:入棧、出棧、複製、交換、產生消費變數(用來執行加減乘除等操作)
  • 本地方法棧

    • 本地方法棧和java虛擬機器棧十分相似,差別不過是java虛擬機器棧是為了java虛擬機器執行位元組碼所服務,而本地方法棧則是為了執行native方法所服務的,所以本地方法也是一個私有的記憶體區域,也是後進先出棧,作用是支撐native方法的呼叫,執行和退出與java虛擬機器棧一樣也會出現以上兩種異常。

執行緒共享部分:共享部分為:MetaSpace(元空間),Java堆

  • 元空間(MetaSpace)與永久代(PermGen)的區別:(用元空間代替永久代)

    • 元空間使用的是本地記憶體,而永久代使用的是jvm的記憶體
    • 字串常量池存在永久代中,容易出現效能問題和記憶體溢位
    • 類和方法的資訊大小難以確定,給永久代的大小指定帶來困難
    • 永久代會為GC帶來不必要的複雜性
  • Java堆(Heap),在虛擬機器啟動時建立

    • 物件例項的分配區域(Java堆的唯一目的)
    • GC管理的主要區域

JVM三大效能調優引數

  • -Xss:規定了每個執行緒虛擬機器棧的大小
  • -Xms:堆的初始值
  • -Xmx:堆能達到的最大值

Java記憶體模型中堆和棧的區別

  • 聯絡:引用物件、陣列時,棧裡定義變數儲存堆中目標的首地址

  • 區別

    • 管理方式:棧自動釋放,堆需要GC
    • 空間大小:棧比堆小
    • 記憶體碎片相關:棧產生的碎片遠小於堆
    • 分配方式:棧支援靜態和動態分配,而堆僅支援動態分配
    • 效率:棧的效率比堆高