面:為什么要使用雙親委派機制去加載類?
答:避免多份同樣字節碼的加載,浪費內存。
類的加載方式
- 隱式加載:new
- 顯示加載:loadClass、forName等
類的裝載過程如下圖:
面:loadClass和forName的區別?
- Class.forName得到的class是已經初始化完成了的 (MySQL加載驅動時,需要調用靜態代碼塊完成一些操作)
- ClassLoader.loadClass得到的class是還沒有鏈接的。(用于Spring IoC中的延遲加載機制)
Java內存模型
JVM內存模型——JDK8如下圖所示:
- 線程私有:程序計數器、虛擬機棧、本地方法棧
- 線程共享:MetaSpace、Java堆
程序計數器(PC)
- 當前線程所執行的字節碼行號指示器(邏輯)
- 通過改變計數器的值來選取下一條需要執行的字節碼指令
- 和線程是一對一的關系即“線程私有”
- 對Java方法計數,如果是Native方法則計數器的值為Undefined
- 不會發生內存泄漏
Java虛擬機棧(Stack)
- Java方法執行的內存模型
- 包含多個棧幀(一個棧幀包括局部變量表、操作棧、動態鏈接、返回地址等,方法的調用即對于棧幀從虛擬機Stack中入棧到出棧的過程)
- 當線程請求的棧深度超過最大值,會拋出 StackOverflowError 異常;
- 棧進行動態擴展時如果無法申請到足夠內存,會拋出 OutOfMemoryError 異常。
本地方法棧
與虛擬機棧相似,主要作用于標注了native的方法。
元空間(MetaSpace)
用于存放已被加載的類信息、常量、靜態變量。
面:談談元空間(MetaSpace)和永久代(PermGen)的區別?
- 均是方法區(JVM的一種規范)的實現
- JDK8后元空間替代了永久代
- 元空間使用本地內存,而永久代使用的是jvm內存,這解決了空間不足的問題。
面:MetaSpace相比PermGen的優勢?
- 字符串常量池(JDK1.7開始移動到Java堆中)存在與永久代中,容易出現性能問題和內存溢出
- 類的方法的信息大小難以確定,給永久代的大小的指定帶來了困難
- 永久代會為GC帶來不必要的復雜性
- 方便HotSpot與其他JVM如Jrockit的集成(因為永久代是HotSpot獨有的)
Java堆(Heap)
- 是對象實例的分配區域
- GC管理的主要區域
面:說說JVM三大性能調優參數-Xms、-Xmx、-Xss的含義?
java -Xms128m -Xmx128m -Xss256k -jar xxx.jar
- -Xss:規定了每個線程虛擬機棧(堆棧)的大小
- -Xms:堆的初始值
- -Xmx:堆能達到的最大值
一般將-Xms與-Xmx設置為同樣的數值,避免堆擴容時發生的內存抖動,影響程序的穩定性。
內存分配策略
- 靜態存儲:編譯時確定每個數據目標在運行時的存儲空間需求
- 棧式存儲:數據區需求在編譯時未知,在運行時模塊入口前確定
- 堆式存儲:編譯時或運行時模塊入口都無法確定需求,需要動態分配
面:談談Java內存模型中堆和棧的區別與聯系?
- 聯系:引用對象、數組時,棧里定義變量來保存堆中目標的首地址
- 管理方式:棧自動釋放,堆需要GC
- 空間大小:一般棧比堆小
- 碎片相關:棧產生的內存碎片遠小于堆
- 分配方式:棧支持靜態和動態分配,而堆僅支持動態分配
- 效率:棧的效率比堆高(棧只有入棧與出棧)
面:請解釋下JDK6和JDK6+下intern()方法的區別?
- JDK6:當調用intern方法時,如果字符串常量池先前已創建出該字符串對象,則返回池中的該字符串的引用。否則將此字符串對象添加到字符串常量池中,并且返回該字符串對象的引用。
- JDK6+:當調用intern方法時,如果字符串常量池先前已創建出該字符串對象,則返回池中該字符串的引用。否則,如果該字符串對象已經存在與Java堆中,則將堆中對此對象的引用添加到字符串常量池中,并且返回該引用;如果堆中不存在該對象,則在字符串常量池中創建該字符串并返回其引用。
最后
針對最近很多人都在面試,我這邊也整理了相當多的面試專題資料,也有其他大廠的面經。希望可以幫助到大家。
下面的面試題答案都整理成文檔筆記。也還整理了一些面試資料&最新2021收集的一些大廠的面試真題(都整理成文檔,小部分截圖),有需要的可以戳這里免費領取
最新整理電子書
這里免費領取](https://docs.qq.com/doc/DSmxTbFJ1cmN1R2dB)
[外鏈圖片轉存中…(img-IAKzt7JK-1624225631036)]
最新整理電子書