文本已收錄至個人GitHub倉庫,歡迎Star:github.com/bin39232820…
種一棵樹最好的時間是十年前,其次是如今
我知道不少人不玩qq了,可是懷舊一下,歡迎加入六脈神劍Java菜鳥學習羣,羣聊號碼:549684836 鼓勵你們在技術的路上寫博客java
絮叨
前面的章節git
今天呢,給你們講關於JVM的面試題,可是太多了,我也挑不全,講講比較典型的,可是全部題目的答案仍是前面四個章節的基礎,我以爲最難的是類文件結構,這個真的搞死人。哈哈,廢話很少說咱們來看題程序員
JVM內存分哪幾個區,每一個區的做用是什麼?
Java虛擬機主要分爲如下一個區: github
- 方法區:
- 有時候也成爲永久代,在該區內不多發生垃圾回收,可是並不表明不發生GC,在這裏進行的GC主要是對方法區裏的常量池和對類 型的卸載
- 方法區主要用來存儲已被虛擬機加載的類的信息、常量、靜態變量和即時編譯器編譯後的代碼等數據。
- 該區域是被線程共享的。
- 方法區裏有一個運行時常量池,用於存放靜態編譯產生的字面量和符號引用。該常量池具備動態性,也就是說常量並不必定是編 譯時肯定,運行時生成的常量也會存在這個常量池中。
- 虛擬機棧:
- 虛擬機棧也就是咱們日常所稱的棧內存,它爲java方法服務,每一個方法在執行的時候都會建立一個棧幀,用於存儲局部變量表、操 做數棧、動態連接和方法出口等信息。
- 虛擬機棧是線程私有的,它的生命週期與線程相同。
- 局部變量表裏存儲的是基本數據類型、returnAddress類型(指向一條字節碼指令的地址)和對象引用,這個對象引用有多是指 向對象起始地址的一個指針,也有多是表明對象的句柄或者與對象相關聯的位置。局部變量所需的內存空間在編譯器間肯定
- 操做數棧的做用主要用來存儲運算結果以及運算的操做數,它不一樣於局部變量表經過索引來訪問,而是壓棧和出棧的方式
- 每一個棧幀都包含一個指向運行時常量池中該棧幀所屬方法的引用,持有這個引用是爲了支持方法調用過程當中的動態鏈接.動態連接就是將常量池中的符號引用在運行期轉化爲直接引用。
- 本地方法棧
- 本地方法棧和虛擬機棧相似,只不過本地方法棧爲Native方法服務。
- 堆
- Java堆是全部線程所共享的一塊內存,在虛擬機啓動時建立,幾乎全部的對象實例都在這裏建立,所以該區域常常發生垃圾回收操做 。
- 程序計數器
- 內存空間小,字節碼解釋器工做時經過改變這個計數值能夠選取下一條須要執行的字節碼指令,分支、循環、跳轉、異常處理和線程恢復等功能都須要依賴這個計數器完成。該內存區域是惟一一個java虛擬機規範沒有規定任何OOM狀況的區域。
如和判斷一個對象是否存活?(或者GC對象的斷定方法)
答案再前面的章節web
簡述Java垃圾回收機制?
在Java中,程序員是不須要顯示的去釋放一個對象的內存的,而是由虛擬機自行執行。在JVM中,有一個垃圾回收線程,它是低優先級的,在正常狀況下是不會執行的,只有在虛擬機空閒或者當前堆內存不足時,纔會觸發執行,掃面那些沒有被任何引用的對象,並將它們添加到要回收的集合中,進行回收。面試
Java中垃圾收集的方法有哪些?
問的3種回收算法 在前面的章節算法
java類加載過程?
問的是類加載的7個過程 加載 驗證 準備 解析 初始化 運行 死亡 這7個過程,每一個過程作了什麼 ,也是再我前面的章節數據庫
類加載器雙親委派模型機制?
簡單來講就是8個字,向上檢查,向下加載。具體能夠看我前面的章節安全
什麼是類加載器,類加載器有哪些?
實現經過類的權限定名獲取該類的二進制字節流的代碼塊叫作類加載器。服務器
主要有一下四種類加載器:
- 啓動類加載器(Bootstrap ClassLoader)用來加載java核心類庫,沒法被java程序直接引用。
- 擴展類加載器(extensions class loader):它用來加載 Java 的擴展庫。Java 虛擬機的實現會提供一個擴展庫目錄。該類加載器在此目錄裏面查找並加載 Java 類。
- 系統類加載器(system class loader):它根據 Java 應用的類路徑(CLASSPATH)來加載 Java 類。通常來講,Java 應用的類都是由它來完成加載的。能夠經過 ClassLoader.getSystemClassLoader()來獲取它。
- 用戶自定義類加載器,經過繼承 java.lang.ClassLoader類的方式實現。
Tomcat 的類加載模型
想一想 Tomcat 爲啥要打破雙親委派模型
首先,咱們來問個問題:
Tomcat 若是使用默認的類加載機制行不行?
咱們思考一下:Tomcat是個web容器, 那麼它要解決什麼問題:
- 一個web容器可能須要部署兩個應用程序,不一樣的應用程序可能會依賴同一個第三方類庫的不一樣版本,不能要求同一個類庫在同一個服務器只有一份,所以要保證每一個應用程序的類庫都是獨立的,保證相互隔離。
- 部署在同一個web容器中相同的類庫相同的版本能夠共享。不然,若是服務器有10個應用程序,那麼要有10份相同的類庫加載進虛擬機,這是扯淡的。
- web容器也有本身依賴的類庫,不能於應用程序的類庫混淆。基於安全考慮,應該讓容器的類庫和程序的類庫隔離開來。
- web容器要支持jsp的修改,咱們知道,jsp 文件最終也是要編譯成class文件才能在虛擬機中運行,但程序運行後修改jsp已是司空見慣的事情,不然要你何用? 因此,web容器須要支持 jsp 修改後不用重啓。
再看看咱們的問題:Tomcat 若是使用默認的類加載機制行不行?
答案是不行的。爲何?咱們看,第一個問題,若是使用默認的類加載器機制,那麼是沒法加載兩個相同類庫的不一樣版本的,默認的累加器是無論你是什麼版本的,只在意你的全限定類名,而且只有一份。第二個問題,默認的類加載器是可以實現的,由於他的職責就是保證惟一性。第三個問題和第一個問題同樣。咱們再看第四個問題,咱們想咱們要怎麼實現jsp文件的熱修改(樓主起的名字),jsp 文件其實也就是class文件,那麼若是修改了,但類名仍是同樣,類加載器會直接取方法區中已經存在的,修改後的jsp是不會從新加載的。那麼怎麼辦呢?咱們能夠直接卸載掉這jsp文件的類加載器,因此你應該想到了,每一個jsp文件對應一個惟一的類加載器,當一個jsp文件修改了,就直接卸載這個jsp類加載器。從新建立類加載器,從新加載jsp文件。
你有沒有遇到過OutOfMemory問題?你是怎麼來處理這個問題的?處理 過程當中有哪些收穫?
常見的緣由
- 內存加載的數據量太大:一次性從數據庫取太多數據;
- 集合類中有對對象的引用,使用後未清空,GC不能進行回收;
- 代碼中存在循環產生過多的重複對象;
- 啓動參數堆內存值小。
JDK 1.8以後Perm Space有哪些變更? MetaSpace⼤⼩默認是⽆限的麼? 仍是大家會經過什麼⽅式來指定⼤⼩?
JDK 1.8後用元空間替代了 Perm Space;字符串常量存放到堆內存中。
MetaSpace大小默認沒有限制,通常根據系統內存的大小。JVM會動態改變此值。
-XX:MetaspaceSize:分配給類元數據空間(以字節計)的初始大小(Oracle邏輯存儲上的初始高水位,the initial high-water-mark)。此值爲估計值,MetaspaceSize的值設置的過大會延長垃圾回收時間。垃圾回收事後,引發下一次垃圾回收的類元數據空間的大小可能會變大。
-XX:MaxMetaspaceSize:分配給類元數據空間的最大值,超過此值就會觸發Full GC,此值默認沒有限制,但應取決於系統內存的大小。JVM會動態地改變此值。
jstack 是⼲什麼的? jstat 呢?若是線上程序週期性地出現卡頓,你懷疑可 能是 GC 致使的,你會怎麼來排查這個問題?線程⽇志⼀般你會看其中的什麼 部分?
jstack 用來查詢 Java 進程的堆棧信息。
jvisualvm 監控內存泄露,跟蹤垃圾回收、執行時內存、cpu分析、線程分析。
StackOverflow異常有沒有遇到過?⼀般你猜想會在什麼狀況下被觸發?如何指定⼀個線程的堆棧⼤⼩?⼀般大家寫多少?
棧內存溢出,通常由棧內存的局部變量過爆了,致使內存溢出。出如今遞歸方法,參數個數過多,遞歸過深,遞歸沒有出口
跟JVM內存相關的幾個核心參數圖解
如何啓動系統的時候設置JVM的啓動參數
結尾
這篇到時候看到好的就補充進去,先說這麼多,而後是實戰纔是最重要的,你要有實際JVM調優經驗,面試纔是加分項,至於理論也僅僅是次要的。
平常求贊
好了各位,以上就是這篇文章的所有內容了,能看到這裏的人呀,都是真粉。
創做不易,各位的支持和承認,就是我創做的最大動力,咱們下篇文章見
六脈神劍 | 文 【原創】若是本篇博客有任何錯誤,請批評指教,不勝感激 !