日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

原创 | 万万没想到,JVM内存结构的面试题可以问的这么难?

發(fā)布時間:2025/3/16 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 原创 | 万万没想到,JVM内存结构的面试题可以问的这么难? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

△Hollis, 一個對Coding有著獨特追求的人△

這是Hollis的第?223?篇原創(chuàng)分享

作者 l Hollis

來源 l Hollis(ID:hollischuang)

在我的博客中,之前有很多文章介紹過JVM內(nèi)存結(jié)構(gòu),相信很多看多我文章的朋友對這部分知識都有一定的了解了。

那么,請大家嘗試著回答一下以下問題:

1、JVM管理的內(nèi)存結(jié)構(gòu)是怎樣的??2、不同的虛擬機在實現(xiàn)運行時內(nèi)存的時候有什么區(qū)別??3、運行時數(shù)據(jù)區(qū)中哪些區(qū)域是線程共享的?哪些是獨享的??4、除了JVM運行時內(nèi)存以外,還有什么區(qū)域可以用嗎??5、堆和棧的區(qū)別是什么??6、Java中的數(shù)組是存儲在堆上還是棧上的??7、Java中的對象創(chuàng)建有多少種方式??8、Java中對象創(chuàng)建的過程是怎么樣的??9、Java中的對象一定在堆上分配內(nèi)存嗎??10、如何獲取堆和棧的dump文件?以上10道題,如果您可以全部準確無誤的回答的話,那說明你真的很了解JVM的內(nèi)存結(jié)構(gòu)以及內(nèi)存分配相關(guān)的知識了,如果有哪些知識點是不了解的,那么本文正好可以幫你答疑解惑。


Q1:JVM管理的內(nèi)存結(jié)構(gòu)是怎樣的?

Java虛擬機在執(zhí)行Java程序的過程中會把他所管理的內(nèi)存劃分為若干個不同的數(shù)據(jù)區(qū)域。《Java虛擬機規(guī)范》中規(guī)定了JVM所管理的內(nèi)存需要包括一下幾個運行時區(qū)域:

Java虛擬機運行時數(shù)據(jù)區(qū)域主要包含了PC寄存器(程序計數(shù)器)、Java虛擬機棧、本地方法棧、Java堆、方法區(qū)以及運行時常量池。

各個區(qū)域有各自不同的作用,關(guān)于各個區(qū)域的作用就不在本文中相信介紹了。

但是,需要注意的是,上面的區(qū)域劃分只是邏輯區(qū)域,規(guī)范對于有些區(qū)域的限制是比較松的,所以不同的虛擬機廠商在實現(xiàn)上,甚至是同一款虛擬機的不同版本也是不盡相同的。


Q2:不同的虛擬機在實現(xiàn)運行時內(nèi)存的時候有什么區(qū)別?

前面提到過《Java虛擬機規(guī)范》定義的JVM運行時所需的內(nèi)存區(qū)域,不同的虛擬機實現(xiàn)上有所不同,而在這么多區(qū)域中,規(guī)范對于方法區(qū)的管理是最寬松的,規(guī)范中關(guān)于這部分的描述如下:

方法區(qū)在虛擬機啟動的時候創(chuàng)建,雖然方法區(qū)是堆的邏輯組成部分,但是簡單的虛擬機實現(xiàn)可以選擇在這個區(qū)域不實現(xiàn)垃圾收集與壓縮。本版本的規(guī)范也不限定實現(xiàn)方法區(qū)的內(nèi)存位置和代碼編譯的管理策略。方法區(qū)的容量可以是固定的,也可以隨著程序執(zhí)行的需求動態(tài)擴展,并在不需要過多的空間時自行收縮。方法區(qū)在實際內(nèi)存空間站可以是不連續(xù)的。

這一規(guī)定,可以說是給了虛擬機廠商很大的自由。

虛擬機規(guī)范對方法區(qū)實現(xiàn)的位置并沒有明確要求,在最著名的HotSopt虛擬機實現(xiàn)中(在Java 8 之前),方法區(qū)僅是邏輯上的獨立區(qū)域,在物理上并沒有獨立于堆而存在,而是位于永久代中。所以,這時候方法區(qū)也是可以被垃圾回收的。

實踐證明,JVM中存在著大量的聲明短暫的對象,還有一些生命周期比較長的對象。為了對他們采用不同的收集策略,采用了分代收集算法,所以HotSpot虛擬機把的根據(jù)對象的年齡不同,把堆分位新生代、老年代和永久代。

在Java 8中 ,HotSpot虛擬機移除了永久代,使用本地內(nèi)存來存儲類元數(shù)據(jù)信息并稱之為:元空間(Metaspace)


Q3:運行時數(shù)據(jù)區(qū)中哪些區(qū)域是線程共享的?哪些是獨享的?

在JVM運行時內(nèi)存區(qū)域中,PC寄存器、虛擬機棧和本地方法棧是線程獨享的。

而Java堆、方法區(qū)是線程共享的。但是值得注意的是,Java堆其實還未每一個線程單獨分配了一塊TLAB空間,這部分空間在分配時是線程獨享的,在使用時是線程共享的。TLAB介紹


Q4:除了JVM運行時內(nèi)存以外,還有什么區(qū)域可以用嗎?

除了我們前面介紹的虛擬機運行時數(shù)據(jù)區(qū)以外,還有一部分內(nèi)存也被頻繁使用,他不是運行時數(shù)據(jù)區(qū)的一部分,也不是Java虛擬機規(guī)范中定義的內(nèi)存區(qū)域,他就是——直接內(nèi)存。

直接內(nèi)存的分配不受Java堆大小的限制,但是他還是會收到服務(wù)器總內(nèi)存的影響。

在JDK 1.4中引入的NIO中,引入了一種基于Channel和Buffer的I/O方式,他可以使用Native函數(shù)直接分配堆外內(nèi)存,然后通過一個存儲在Java堆中的DirectByteBuffer對象作為這塊內(nèi)存的應(yīng)用進行操作。

Q5:堆和棧的區(qū)別是什么?

堆和棧(虛擬機棧)是完全不同的兩塊內(nèi)存區(qū)域,一個是線程獨享的,一個是線程共享的,二者之間最大的區(qū)別就是存儲的內(nèi)容不同:

堆中主要存放對象實例。?
棧(局部變量表)中主要存放各種基本數(shù)據(jù)類型、對象的引用。


Q6:Java中的數(shù)組是存儲在堆上還是棧上的?

在Java中,數(shù)組同樣是一個對象,所以對象在內(nèi)存中如何存放同樣適用于數(shù)組;

所以,數(shù)組的實例是保存在堆中,而數(shù)組的引用是保存在棧上的。

Q7:Java中的對象創(chuàng)建有多少種方式?

Java中共有5種方式可以創(chuàng)建一個對象。

最簡單的方式就是使用new關(guān)鍵字。

User user = new User();

除此以外,還可以使用反射機制創(chuàng)建對象:

User user = User.class.newInstance();

或者使用Constructor類的newInstance:

Constructor<User> constructor = User.class.getConstructor();User user = constructor.newInstance(););
User user = constructor.newInstance();

除此之外還可以使用clone方法和反序列化的方式,這兩種方式不常用并且代碼比較復雜,就不在這里展示了,感興趣的可以自行了解下。


Q8:Java中對象創(chuàng)建的過程是怎么樣的?

對于一個普通的Java對象的創(chuàng)建,大致過程如下:

1、虛擬機遇到new指令,到常量池定位到這個類的符號引用。?
2、檢查符號引用代表的類是否被加載、解析、初始化過。?
3、虛擬機為對象分配內(nèi)存。?
4、虛擬機將分配到的內(nèi)存空間都初始化為零值。?
5、虛擬機對對象進行必要的設(shè)置。?
6、執(zhí)行方法,成員變量進行初始化。


Q9:Java中的對象一定在堆上分配內(nèi)存嗎?

前面我們說過,Java堆中主要保存了對象實例,但是,隨著JIT編譯期的發(fā)展與逃逸分析技術(shù)逐漸成熟,棧上分配、標量替換優(yōu)化技術(shù)將會導致一些微妙的變化,所有的對象都分配到堆上也漸漸變得不那么“絕對”了。

其實,在編譯期間,JIT會對代碼做很多優(yōu)化。其中有一部分優(yōu)化的目的就是減少內(nèi)存堆分配壓力,其中一種重要的技術(shù)叫做逃逸分析。

如果JIT經(jīng)過逃逸分析,發(fā)現(xiàn)有些對象沒有逃逸出方法,那么有可能堆內(nèi)存分配會被優(yōu)化成棧內(nèi)存分配。(關(guān)于逃逸分析和棧上分配可以參考:深入理解Java中的逃逸分析、對象并不一定都是在堆上分配內(nèi)存的)

Q10:怎么如何獲取堆和棧的dump文件?

Java Dump,Java虛擬機的運行時快照。將Java虛擬機運行時的狀態(tài)和信息保存到文件。

可以使用在服務(wù)器上使用jmap命令來獲取堆dump,使用jstack命令來獲取線程的調(diào)用棧dump。(關(guān)于jmap和jstack可以參考:Java命令學習系列(三)——Jmap、Java命令學習系列(二)——Jstack)


以上,就是本文的全部內(nèi)容,對于其中的很多知識點,作者并未逐一展開,感興趣的朋友可以自行學習一下,關(guān)于Java虛擬機相關(guān)知識,推薦三本書:《深入理解Java虛擬機》、《HotSpot實戰(zhàn)》以及《Java虛擬機規(guī)范(第8版)》,本文中內(nèi)容也參考了這三本書中很多內(nèi)容。希望對你有幫助。



Java工程師成神之路系列文章

在 GitHub 更新中,歡迎關(guān)注,歡迎star。

?

直面Java第262期:volatile是如何解決有序性問題的?

深入并發(fā)第009期:到底什么是Java內(nèi)存模型?

- MORE | 更多精彩文章 -

  • 推薦幾個來自BATJ等一線互聯(lián)網(wǎng)公司的大神的公眾號!

  • Apache的架構(gòu)師們遵循的30條設(shè)計原則

  • 一個員工的離職成本到底有多恐怖!

  • 2019年美團,滴滴,蘑菇街Java大數(shù)據(jù)面經(jīng)分享!


如果你喜歡本文,

請長按二維碼,關(guān)注?Hollis.

轉(zhuǎn)發(fā)至朋友圈,是對我最大的支持。


好文章,我在看??

總結(jié)

以上是生活随笔為你收集整理的原创 | 万万没想到,JVM内存结构的面试题可以问的这么难?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。