您好,登錄后才能下訂單哦!
前言:
JVM是Java Virtual Machine(Java虛擬機(jī))的縮寫,JVM是一種用于計(jì)算設(shè)備的規(guī)范,它是一個(gè)虛構(gòu)出來的計(jì)算機(jī),是通過在實(shí)際的計(jì)算機(jī)上仿真模擬各種計(jì)算機(jī)功能來實(shí)現(xiàn)的。引入Java語言虛擬機(jī)后,Java語言在不同平臺(tái)上運(yùn)行時(shí)不需要重新編譯。Java語言使用Java虛擬機(jī)屏蔽了與具體平臺(tái)相關(guān)的信息,使得Java語言編譯程序只需生成在Java虛擬機(jī)上運(yùn)行的目標(biāo)代碼(字節(jié)碼),就可以在多種平臺(tái)上不加修改地運(yùn)行。
下面,大家可以嘗試著回答一下以下問題:
1、JVM管理的內(nèi)存結(jié)構(gòu)是怎樣的?
2、不同的虛擬機(jī)在實(shí)現(xiàn)運(yùn)行時(shí)內(nèi)存的時(shí)候有什么區(qū)別?
3、運(yùn)行時(shí)數(shù)據(jù)區(qū)中哪些區(qū)域是線程共享的?哪些是獨(dú)享的?
4、除了JVM運(yùn)行時(shí)內(nèi)存以外,還有什么區(qū)域可以用嗎?
5、堆和棧的區(qū)別是什么?
6、Java中的數(shù)組是存儲(chǔ)在堆上還是棧上的?
7、Java中的對(duì)象創(chuàng)建有多少種方式?
8、Java中對(duì)象創(chuàng)建的過程是怎么樣的?
9、Java中的對(duì)象一定在堆上分配內(nèi)存嗎?
10、如何獲取堆和棧的dump文件?
以上10道題,如果您可以全部準(zhǔn)確無誤的回答的話,那說明你真的很了解JVM的內(nèi)存結(jié)構(gòu)以及內(nèi)存分配相關(guān)的知識(shí)了,如果有哪些知識(shí)點(diǎn)是不了解的,那么本文正好可以幫你答疑解惑。
1:JVM管理的內(nèi)存結(jié)構(gòu)是怎樣的?
Java虛擬機(jī)在執(zhí)行Java程序的過程中會(huì)把他所管理的內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)域?!禞ava虛擬機(jī)規(guī)范》中規(guī)定了JVM所管理的內(nèi)存需要包括一下幾個(gè)運(yùn)行時(shí)區(qū)域:
Java虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)域主要包含了PC寄存器(程序計(jì)數(shù)器)、Java虛擬機(jī)棧、本地方法棧、Java堆、方法區(qū)以及運(yùn)行時(shí)常量池。
各個(gè)區(qū)域有各自不同的作用,關(guān)于各個(gè)區(qū)域的作用就不在本文中相信介紹了。
但是,需要注意的是,上面的區(qū)域劃分只是邏輯區(qū)域,規(guī)范對(duì)于有些區(qū)域的限制是比較松的,所以不同的虛擬機(jī)廠商在實(shí)現(xiàn)上,甚至是同一款虛擬機(jī)的不同版本也是不盡相同的。
2:不同的虛擬機(jī)在實(shí)現(xiàn)運(yùn)行時(shí)內(nèi)存的時(shí)候有什么區(qū)別?
前面提到過《Java虛擬機(jī)規(guī)范》定義的JVM運(yùn)行時(shí)所需的內(nèi)存區(qū)域,不同的虛擬機(jī)實(shí)現(xiàn)上有所不同,而在這么多區(qū)域中,規(guī)范對(duì)于方法區(qū)的管理是最寬松的,規(guī)范中關(guān)于這部分的描述如下:
方法區(qū)在虛擬機(jī)啟動(dòng)的時(shí)候創(chuàng)建,雖然方法區(qū)是堆的邏輯組成部分,但是簡(jiǎn)單的虛擬機(jī)實(shí)現(xiàn)可以選擇在這個(gè)區(qū)域不實(shí)現(xiàn)垃圾收集與壓縮。本版本的規(guī)范也不限定實(shí)現(xiàn)方法區(qū)的內(nèi)存位置和代碼編譯的管理策略。方法區(qū)的容量可以是固定的,也可以隨著程序執(zhí)行的需求動(dòng)態(tài)擴(kuò)展,并在不需要過多的空間時(shí)自行收縮。方法區(qū)在實(shí)際內(nèi)存空間站可以是不連續(xù)的。
這一規(guī)定,可以說是給了虛擬機(jī)廠商很大的自由。
虛擬機(jī)規(guī)范對(duì)方法區(qū)實(shí)現(xiàn)的位置并沒有明確要求,在最著名的HotSopt虛擬機(jī)實(shí)現(xiàn)中(在Java 8 之前),方法區(qū)僅是邏輯上的獨(dú)立區(qū)域,在物理上并沒有獨(dú)立于堆而存在,而是位于永久代中。所以,這時(shí)候方法區(qū)也是可以被垃圾回收的。
實(shí)踐證明,JVM中存在著大量的聲明短暫的對(duì)象,還有一些生命周期比較長(zhǎng)的對(duì)象。為了對(duì)他們采用不同的收集策略,采用了分代收集算法,所以HotSpot虛擬機(jī)把的根據(jù)對(duì)象的年齡不同,把堆分位新生代、老年代和永久代。
在Java 8中 ,HotSpot虛擬機(jī)移除了永久代,使用本地內(nèi)存來存儲(chǔ)類元數(shù)據(jù)信息并稱之為:元空間(Metaspace)
?
3:運(yùn)行時(shí)數(shù)據(jù)區(qū)中哪些區(qū)域是線程共享的?哪些是獨(dú)享的?
在JVM運(yùn)行時(shí)內(nèi)存區(qū)域中,PC寄存器、虛擬機(jī)棧和本地方法棧是線程獨(dú)享的。
而Java堆、方法區(qū)是線程共享的。但是值得注意的是,Java堆其實(shí)還未每一個(gè)線程單獨(dú)分配了一塊TLAB空間,這部分空間在分配時(shí)是線程獨(dú)享的,在使用時(shí)是線程共享的。
4:除了JVM運(yùn)行時(shí)內(nèi)存以外,還有什么區(qū)域可以用嗎?
除了我們前面介紹的虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)以外,還有一部分內(nèi)存也被頻繁使用,他不是運(yùn)行時(shí)數(shù)據(jù)區(qū)的一部分,也不是Java虛擬機(jī)規(guī)范中定義的內(nèi)存區(qū)域,他就是——直接內(nèi)存。
直接內(nèi)存的分配不受Java堆大小的限制,但是他還是會(huì)收到服務(wù)器總內(nèi)存的影響。
在JDK 1.4中引入的NIO中,引入了一種基于Channel和Buffer的I/O方式,他可以使用Native函數(shù)直接分配堆外內(nèi)存,然后通過一個(gè)存儲(chǔ)在Java堆中的DirectByteBuffer對(duì)象作為這塊內(nèi)存的應(yīng)用進(jìn)行操作。
?
5:堆和棧的區(qū)別是什么?
堆和棧(虛擬機(jī)棧)是完全不同的兩塊內(nèi)存區(qū)域,一個(gè)是線程獨(dú)享的,一個(gè)是線程共享的,二者之間最大的區(qū)別就是存儲(chǔ)的內(nèi)容不同:
堆中主要存放對(duì)象實(shí)例。
棧(局部變量表)中主要存放各種基本數(shù)據(jù)類型、對(duì)象的引用。
6:Java中的數(shù)組是存儲(chǔ)在堆上還是棧上的?
在Java中,數(shù)組同樣是一個(gè)對(duì)象,所以對(duì)象在內(nèi)存中如何存放同樣適用于數(shù)組;
所以,數(shù)組的實(shí)例是保存在堆中,而數(shù)組的引用是保存在棧上的。
?
Q7:Java中的對(duì)象創(chuàng)建有多少種方式?
Java中共有5種方式可以創(chuàng)建一個(gè)對(duì)象。
最簡(jiǎn)單的方式就是使用new關(guān)鍵字。
User user = new User();
除此以外,還可以使用反射機(jī)制創(chuàng)建對(duì)象:
User user = User.class.newInstance();
或者使用Constructor類的newInstance:
Constructorconstructor=User.class.getConstructor();User user =constructor.newInstance();
除此之外還可以使用clone方法和反序列化的方式,這兩種方式不常用并且代碼比較復(fù)雜,就不在這里展示了,感興趣的可以自行了解下。
8:Java中對(duì)象創(chuàng)建的過程是怎么樣的?
對(duì)于一個(gè)普通的Java對(duì)象的創(chuàng)建,大致過程如下:
1、虛擬機(jī)遇到new指令,到常量池定位到這個(gè)類的符號(hào)引用。
2、檢查符號(hào)引用代表的類是否被加載、解析、初始化過。
3、虛擬機(jī)為對(duì)象分配內(nèi)存。
4、虛擬機(jī)將分配到的內(nèi)存空間都初始化為零值。
5、虛擬機(jī)對(duì)對(duì)象進(jìn)行必要的設(shè)置。
6、執(zhí)行方法,成員變量進(jìn)行初始化。
9:Java中的對(duì)象一定在堆上分配內(nèi)存嗎?
前面我們說過,Java堆中主要保存了對(duì)象實(shí)例,但是,隨著JIT編譯期的發(fā)展與逃逸分析技術(shù)逐漸成熟,棧上分配、標(biāo)量替換優(yōu)化技術(shù)將會(huì)導(dǎo)致一些微妙的變化,所有的對(duì)象都分配到堆上也漸漸變得不那么“絕對(duì)”了。
其實(shí),在編譯期間,JIT會(huì)對(duì)代碼做很多優(yōu)化。其中有一部分優(yōu)化的目的就是減少內(nèi)存堆分配壓力,其中一種重要的技術(shù)叫做逃逸分析。
如果JIT經(jīng)過逃逸分析,發(fā)現(xiàn)有些對(duì)象沒有逃逸出方法,那么有可能堆內(nèi)存分配會(huì)被優(yōu)化成棧內(nèi)存分配。
10:怎么如何獲取堆和棧的dump文件?
Java Dump,Java虛擬機(jī)的運(yùn)行時(shí)快照。將Java虛擬機(jī)運(yùn)行時(shí)的狀態(tài)和信息保存到文件。
可以使用在服務(wù)器上使用jmap命令來獲取堆dump,使用jstack命令來獲取線程的調(diào)用棧dump。
讀者福利
針對(duì)于上面的面試題我總結(jié)出了互聯(lián)網(wǎng)公司java程序員面試涉及到的絕大部分面試題及答案做成了文檔和架構(gòu)視頻資料免費(fèi)分享給大家(包括Dubbo、Redis、Netty、zookeeper、Spring cloud、分布式、高并發(fā)等架構(gòu)技術(shù)資料),希望能幫助到您面試前的復(fù)習(xí)且找到一個(gè)好的工作,也節(jié)省大家在網(wǎng)上搜索資料的時(shí)間來學(xué)習(xí)。合理利用自己每一分每一秒的時(shí)間來學(xué)習(xí)提升自己,不要再用"沒有時(shí)間“來掩飾自己思想上的懶惰!
獲取方式:資料整理不易,轉(zhuǎn)×××某人 免費(fèi)領(lǐng)取。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。