更新時間:2023-02-03 11:49:09 來源:動力節點 瀏覽1288次
Jvm既可以操作系統平臺相關信息又可以做到屏蔽作用,這就可以讓Java程序只需要在Java虛擬機上實現在不同的平臺上運行,所以我們在面試相關崗位的時候,Java Jvm方面的面試題會被頻繁的問到,所以,正準備面試的同學,Java Jvm的面試題最好了解一些。
1.運行時數據區是什么
虛擬機在執行程序過程中,將虛擬機內部的內存區域劃分成不同的數據區域。每個數據區都具有自己的生命周期和功能作用。
對于這一部分區域,我們可以根據線程的私有和線程共享來進行分類。
從線程獨占角度 來看主要又 ;pc程序計數器 ,java虛擬機棧 ,本地方法棧
而線程共享來看則主要是的:堆和方法區。
2.堆的作用是什么
答題整體思路:點名堆內存的主要作用,之后深入至堆內存中年輕代、老年代的整體的布局情況。可以順帶提及minorgc和Full gc發生的時機。
如果時間充裕的話還可以擴展衍生至對象創建,對象分配的話題。一個小小的堆內存可以回答和擴展的點真的很多。
關于JVM中的堆內存,其主要功能就是用于存放java中的對象實例信息,同時在java虛擬機規范中也明確指出,對象信息和數組信息的創建應該帶都分配在堆內存之中。
當我們知道了堆的主要作用后,接下來我們可以看看jvm的基本內存布局,整體來看在jvm的堆內存中,其主要主要存儲區域分為年輕代和老年代。如果使用的版本是jdk8之前的版本則還有永久代的概念,而到了jdk8之后永久代則被元空間所取代。
對于我們的堆內存的年輕代來看,其內部又劃分為兩個survior區和一個eden區。這樣設計的目的也主要是為了能更好的進行垃圾回收。我們都知道java中的對象通常朝生夕死,大部分對象的存活生命周期還是很短的,為了降低垃圾回收的頻率,提升jvm的整體性能。所以設定兩個survior區來進行垃圾的回收和處理。
如果細致來看,此時我們對于survior為什么設定兩個?討論這個問題的前提在于我們假定垃圾回收采用的算法是復制算法。
對于復制算法其主要過程如下:
1)Eden 區活著的對象 + From Survivor 存儲的對象被復制到 To Survivor ;
2) 清空 Eden 和 From Survivor ;
3) 顛倒 From Survivor 和 To Survivor 的邏輯關系: From 變 To , To 變 From 。
說清楚復制算法之后,我們在開始討論為什么設定surivor內存區域為兩個。
這個問題我們來看0個,如果不設定survior區域,那么eden區滿了之后就需要觸發gc,此時幸存對象保存至老年代,這樣老年代很快就會被填滿,加劇了full gc所帶來的性能損耗。
如果設定一個,我們都知道對于年輕代區而言,Eden區和suriovr區域的大小比為8:1,我們假設內存為9M則,eden占據8M,surivior占據1M,此時如果幸存區內容為0.5M則此時我們,此時surivior很快被填滿,同時如果surivior作為對象分配內存的起點,此時又是會很快被填滿。
在只有一個 Survivor 的情況下,無論 Eden 和 Survivor 的比例怎么設置,總體上看在新生代空間滿一半的時候就會觸發一次 Minor gc 。那有沒有提升的空間呢?比如說永遠在新生代空間滿 80% 的時候才觸發 Minor gc ?
此時就引出設計兩個serviceor空間( From Survivor 和 To Survivor )的設計思路。此時把 Eden : From Survivor : To Survivor 空間大小設成 8 : 1 : 1 。
對象總是在 Eden 區出生, From Survivor 保存當前的幸存對象, To Survivor 為空。這樣僅當eden區滿之后才會觸發minorgc,垃圾回收的頻率被進一步降低,性能的影響也得以平衡。
3.方法區的作用是什么?
方法區用于存儲被虛擬機加載的類型信息、常量、靜態變量、即時編譯器編譯后的代碼緩存等數據。
JDK8 之前使用永久代實現方法區,容易內存溢出,因為永久代有 上限,即使不設置也有默認大小。JDK7 把放在永久代的字符串常量池、靜態變量等移出,JDK8 中永久代完全廢棄,改用在本地內存中實現的元空間代替,把 JDK 7 中永久代剩余內容(主要是類型信息)全部移到元空間。
虛擬機規范對方法區的約束寬松,除和堆一樣不需要連續內存和可選擇固定大小/可擴展外,還可以不實現垃圾回收。垃圾回收在方法區出現較少,主要目標針對常量池和類型卸載。如果方法區無法滿足新的內存分配需求,將拋出 OutOfMemoryError
4.運行時常量池作用以及其同類文件中常量池的區別
運行時常量池是方法區的一部分,Class 文件中除了有類的版本、字段、方法、接口等描述信息外,還有一項信息是常量池表,用于存放編譯器生成的各種字面量與符號引用,這部分內容在類加載后存放到運行時常量池。一般除了保存 Class 文件中描述的符號引用外,還會把符號引用翻譯的直接引用也存儲在運行時常量池。
運行時常量池相對于 Class 文件常量池的一個重要特征是動態性,Java 不要求常量只有編譯期才能產生,運行期間也可以將新的常量放入池中,這種特性利用較多的是 String 的 方法。
運行時常量池是方法區的一部分,受到方法區內存的限制,當常量池無法再申請到內存時會拋出 OutOfMemoryError。
對于class 文件中的常量池,我們將 java 代碼通過 javac 編譯為 class 文件,接下來再運行 java 程序的時候就完全不需要 java 文件了,只需要 class 文件即可。而 class 文件是保存在本地磁盤上的文件,里面全是0101的字節碼,或者說是字符串,那各個字符串之間如何產生聯系呢?那就是通過常量池。
對于class常量池而言其在編譯的時候每個class都有的,在編譯階段,主要存放的是常量的符號引用。
而運行時常量池是在類加載完成之后,將每個class常量池中的符號引用值轉存到運行時常量池中。兩者產生時機并不相同,同時類常量池時靜態的,而運行時常量池時動態的。
5.jvm中垃圾收集器有那些
一:Serial 收集器
Serial收集器是最基本的、發展歷史最悠久的收集器。
特點:單線程、簡單高效,對于限定單個CPU的環境來說,Serial收集器由于沒有線程交互的開銷,專心做垃圾收集自然可以獲得最高的單線程手機效率。收集器進行垃圾回收時,必須暫停其他所有的工作線程,直到它結束(Stop The World)。
二:ParNew收集器
ParNew收集器其實就是Serial收集器的多線程版本。
除了使用多線程外其余行為均和Serial收集器一模一樣(參數控制、收集算法、Stop The World、對象分配規則、回收策略等)。
特點:多線程、ParNew收集器默認開啟的收集線程數與CPU的數量相同,在CPU非常多的環境中,可以使用-XX:ParallelgcThreads參數來限制垃圾收集的線程數。
三:Serial Old 收集器
Serial Old是Serial收集器的老年代版本。
特點:同樣是單線程收集器,但是面向老老年代的垃圾收集。采用標記-整理算法。
四:Parallel Old 收集器
概述:是Parallel Scavenge收集器的老年代版本。
特點:多線程,采用標記-整理算法。
五:CMS收集器
全稱(Concurrent Mark Sweep)一種以獲取最短回收停頓時間為目標的收集器。
特點:基于標記-清除算法實現。并發收集、低停頓。
應用場景:適用于注重服務的響應速度,希望系統停頓時間最短,給用戶帶來更好的體驗等場景下。如web程序、b/s服務。
因為采用標記-清除算法所以會存在空間碎片的問題,導致大對象無法分配空間,不得不提前觸發一次Full gc。
以上就是“大廠通用的Java jvm面試題”,你能回答上來嗎?如果想要了解更多的Java面試題相關內容,可以關注動力節點Java官網。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習