1. 說一下 JVM 的主要組成部分奕污?及其作用姓蜂?
? ? ? ?類加載器(ClassLoader)
運行時數(shù)據(jù)區(qū)(Runtime Data Area)
執(zhí)行引擎(Execution Engine)
本地庫接口(Native Interface)
組件的作用:首先通過類加載器(ClassLoader)會把 Java 代碼轉(zhuǎn)換成字節(jié)碼按厘,運行時數(shù)據(jù)區(qū)(Runtime Data Area)再把字節(jié)碼加載到內(nèi)存中,而字節(jié)碼文件只是 JVM 的一套指令集規(guī)范钱慢,并不能直接交個底層操作系統(tǒng)去執(zhí)行,因此需要特定的命令解析器執(zhí)行引擎(Execution Engine)卿堂,將字節(jié)碼翻譯成底層系統(tǒng)指令束莫,再交由 CPU 去執(zhí)行,而這個過程中需要調(diào)用其他語言的本地庫接口(Native Interface)來實現(xiàn)整個程序的功能草描。
2. 說一下 JVM 運行時數(shù)據(jù)區(qū)览绿?
不同虛擬機的運行時數(shù)據(jù)區(qū)可能略微有所不同,但都會遵從 Java 虛擬機規(guī)范穗慕, Java 虛擬機規(guī)范規(guī)定的區(qū)域分為以下 5 個部分:
程序計數(shù)器(Program Counter Register):當前線程所執(zhí)行的字節(jié)碼的行號指示器饿敲,字節(jié)碼解析器的工作是通過改變這個計數(shù)器的值,來選取下一條需要執(zhí)行的字節(jié)碼指令逛绵,分支怀各、循環(huán)、跳轉(zhuǎn)术浪、異常處理瓢对、線程恢復等基礎功能,都需要依賴這個計數(shù)器來完成胰苏;
Java 虛擬機棧(Java Virtual Machine Stacks):用于存儲局部變量表硕蛹、操作數(shù)棧、動態(tài)鏈接硕并、方法出口等信息法焰;
本地方法棧(Native Method Stack):與虛擬機棧的作用是一樣的,只不過虛擬機棧是服務 Java 方法的倔毙,而本地方法棧是為虛擬機調(diào)用 Native 方法服務的埃仪;
Java 堆(Java Heap):Java 虛擬機中內(nèi)存最大的一塊,是被所有線程共享的普监,幾乎所有的對象實例都在這里分配內(nèi)存贵试;
方法區(qū)(Methed Area):用于存儲已被虛擬機加載的類信息琉兜、常量、靜態(tài)變量毙玻、即時編譯后的代碼等數(shù)據(jù)豌蟋。
3. 說一下堆棧的區(qū)別?
功能方面:堆是用來存放對象的桑滩,棧是用來執(zhí)行程序的梧疲。
共享性:堆是線程共享的,棧是線程私有的运准。
空間大谢系:堆大小遠遠大于棧。
4. 隊列和棧是什么胁澳?有什么區(qū)別该互?
隊列和棧都是被用來預存儲數(shù)據(jù)的。
隊列允許先進先出檢索元素韭畸,但也有例外的情況宇智,Deque 接口允許從兩端檢索元素。
棧和隊列很相似胰丁,但它運行對元素進行后進先出進行檢索随橘。
5. 什么是雙親委派模型?
在介紹雙親委派模型之前先說下類加載器锦庸。對于任意一個類机蔗,都需要由加載它的類加載器和這個類本身一同確立在 JVM 中的唯一性,每一個類加載器甘萧,都有一個獨立的類名稱空間萝嘁。類加載器就是根據(jù)指定全限定名稱將 class 文件加載到 JVM 內(nèi)存,然后再轉(zhuǎn)化為 class 對象幔嗦。
類加載器分類:
啟動類加載器(Bootstrap ClassLoader)酿愧,是虛擬機自身的一部分,用來加載Java_HOME/lib/目錄中的邀泉,或者被 -Xbootclasspath 參數(shù)所指定的路徑中并且被虛擬機識別的類庫嬉挡;
其他類加載器:
擴展類加載器(Extension ClassLoader):負責加載\lib\ext目錄或Java. ext. dirs系統(tǒng)變量指定的路徑中的所有類庫;
應用程序類加載器(Application ClassLoader)汇恤。負責加載用戶類路徑(classpath)上的指定類庫庞钢,我們可以直接使用這個類加載器。一般情況因谎,如果我們沒有自定義類加載器默認就是用這個加載器基括。
雙親委派模型:如果一個類加載器收到了類加載的請求,它首先不會自己去加載這個類财岔,而是把這個請求委派給父類加載器去完成风皿,每一層的類加載器都是如此河爹,這樣所有的加載請求都會被傳送到頂層的啟動類加載器中,只有當父加載無法完成加載請求(它的搜索范圍中沒找到所需的類)時桐款,子加載器才會嘗試去加載類咸这。
6. 說一下類裝載的執(zhí)行過程?
類裝載分為以下 5 個步驟:
加載:根據(jù)查找路徑找到相應的 class 文件然后導入魔眨;
檢查:檢查加載的 class 文件的正確性媳维;
準備:給類中的靜態(tài)變量分配內(nèi)存空間;
解析:虛擬機將常量池中的符號引用替換成直接引用的過程遏暴。符號引用就理解為一個標示侄刽,而在直接引用直接指向內(nèi)存中的地址;
初始化:對靜態(tài)變量和靜態(tài)代碼塊執(zhí)行初始化工作朋凉。
7. 怎么判斷對象是否可以被回收州丹?
一般有兩種方法來判斷:
引用計數(shù)器:為每個對象創(chuàng)建一個引用計數(shù),有對象引用時計數(shù)器 +1侥啤,引用被釋放時計數(shù) -1当叭,當計數(shù)器為 0 時就可以被回收。它有一個缺點不能解決循環(huán)引用的問題盖灸;
可達性分析:從 GC Roots 開始向下搜索,搜索所走過的路徑稱為引用鏈磺芭。當一個對象到 GC Roots 沒有任何引用鏈相連時赁炎,則證明此對象是可以被回收的。
8. Java 中都有哪些引用類型钾腺?
強引用:發(fā)生 gc 的時候不會被回收徙垫。
軟引用:有用但不是必須的對象,在發(fā)生內(nèi)存溢出之前會被回收放棒。
弱引用:有用但不是必須的對象姻报,在下一次GC時會被回收。
虛引用(幽靈引用/幻影引用):無法通過虛引用獲得對象间螟,用 PhantomReference 實現(xiàn)虛引用吴旋,虛引用的用途是在 gc 時返回一個通知。
如果您感覺文章對您有所幫助厢破,請讓更多人看到荣瑟!
1.點贊此篇文章,并評論一句摩泪!
2.轉(zhuǎn)發(fā)此篇文章 給予作者支持笆焰!
3.微信搜索 ~ 關注微信公眾號:程序員知識碼頭? 獲取學習資料一份,每天準時發(fā)技術文章见坑!