一定掌握的JVM內(nèi)存管理知識(shí)都有什么

本篇文章給大家分享的是有關(guān)一定掌握的JVM內(nèi)存管理知識(shí)都有什么,小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著小編一起來(lái)看看吧。

10余年的高縣網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開(kāi)發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。營(yíng)銷型網(wǎng)站的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整高縣建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無(wú)論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)公司從事“高縣網(wǎng)站設(shè)計(jì)”,“高縣網(wǎng)站推廣”以來(lái),每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。

Java 引以為豪的就是它的自動(dòng)內(nèi)存管理機(jī)制。相比于 C++的手動(dòng)內(nèi)存管理、復(fù)雜難以理解的指針等,Java 程序?qū)懫饋?lái)就方便的多。

然而這種呼之即來(lái)?yè)]之即去的內(nèi)存申請(qǐng)和釋放方式,自然也有它的代價(jià)。為了管理這些快速的內(nèi)存申請(qǐng)釋放操作,就必須引入一個(gè)池子來(lái)延遲這些內(nèi)存區(qū)域的回收操作。

我們常說(shuō)的內(nèi)存回收,就是針對(duì)這個(gè)池子的操作。我們把上面說(shuō)的這個(gè)池子,叫作堆,可以暫時(shí)把它看成一個(gè)整體。

JVM 內(nèi)存布局

Java 程序的數(shù)據(jù)結(jié)構(gòu)是非常豐富的。其中的內(nèi)容,舉一些例子:

靜態(tài)成員變

動(dòng)態(tài)成員變量

區(qū)域變量

短小緊湊的對(duì)象聲明

龐大復(fù)雜的內(nèi)存申請(qǐng)

我們先看一下 JVM 的內(nèi)存布局。隨著 Java 的發(fā)展,內(nèi)存布局一直在調(diào)整之中。比如,Java 8 及之后的版本,徹底移除了持久代,而使用 Metaspace 來(lái)進(jìn)行替代。這也表示著 -XX:PermSize 和 -XX:MaxPermSize 等參數(shù)調(diào)優(yōu),已經(jīng)沒(méi)有了意義。但大體上,比較重要的內(nèi)存區(qū)域是固定的。

一定掌握的JVM內(nèi)存管理知識(shí)都有什么

JVM 內(nèi)存區(qū)域劃分如圖所示,從圖中我們可以看出:

  •  JVM 堆中的數(shù)據(jù)是共享的,是占用內(nèi)存最大的一塊區(qū)域。

  •  可以執(zhí)行字節(jié)碼的模塊叫作執(zhí)行引擎。

  •  執(zhí)行引擎在線程切換時(shí)怎么恢復(fù)?依靠的就是程序計(jì)數(shù)器。

  •  JVM 的內(nèi)存劃分與多線程是息息相關(guān)的。像我們程序中運(yùn)行時(shí)用到的棧,以及本地方法棧,它們的維度都是線程。

  •  本地內(nèi)存包含元數(shù)據(jù)區(qū)和一些直接內(nèi)存。

虛擬機(jī)棧

Java 虛擬機(jī)棧是基于線程的。哪怕你只有一個(gè) main() 方法,也是以線程的方式運(yùn)行的。在線程的生命周期中,參與計(jì)算的數(shù)據(jù)會(huì)頻繁地入棧和出棧,棧的生命周期是和線程一樣的。

棧里的每條數(shù)據(jù),就是棧幀。在每個(gè) Java 方法被調(diào)用的時(shí)候,都會(huì)創(chuàng)建一個(gè)棧幀,并入棧。一旦完成相應(yīng)的調(diào)用,則出棧。所有的棧幀都出棧后,線程也就結(jié)束了。每個(gè)棧幀,都包含四個(gè)區(qū)域:

  •  局部變量表

  •  操作數(shù)棧

  •  動(dòng)態(tài)連接

  •  返回地址 

我們的應(yīng)用程序,就是在不斷操作這些內(nèi)存空間中完成的。

一定掌握的JVM內(nèi)存管理知識(shí)都有什么

本地方法棧是和虛擬機(jī)棧非常相似的一個(gè)區(qū)域,它服務(wù)的對(duì)象是 native 方法。你甚至可以認(rèn)為虛擬機(jī)棧和本地方法棧是同一個(gè)區(qū)域,這并不影響我們對(duì) JVM 的了解。

這里有一個(gè)比較特殊的數(shù)據(jù)類型叫作 returnAdress。因?yàn)檫@種類型只存在于字節(jié)碼層面,所以我們平常打交道的比較少。對(duì)于 JVM 來(lái)說(shuō),程序就是存儲(chǔ)在方法區(qū)的字節(jié)碼指令,而 returnAddress 類型的值就是指向特定指令內(nèi)存地址的指針。

一定掌握的JVM內(nèi)存管理知識(shí)都有什么

  •  這里有一個(gè)兩層的棧。第一層是棧幀,對(duì)應(yīng)著方法;第二層是方法的執(zhí)行,對(duì)應(yīng)著操作數(shù)。注意千萬(wàn)不要搞混了。

  •  你可以看到,所有的字節(jié)碼指令,其實(shí)都會(huì)抽象成對(duì)棧的入棧出棧操作。執(zhí)行引擎只需要傻瓜式的按順序執(zhí)行,就可以保證它的正確性。

程序計(jì)數(shù)器

既然是線程,就代表它在獲取 CPU 時(shí)間片上,是不可預(yù)知的,需要有一個(gè)地方,對(duì)線程正在運(yùn)行的點(diǎn)位進(jìn)行緩沖記錄,以便在獲取 CPU 時(shí)間片時(shí)能夠快速恢復(fù)。

程序計(jì)數(shù)器是一塊較小的內(nèi)存空間,它的作用可以看作是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器。這里面存的,就是當(dāng)前線程執(zhí)行的進(jìn)度。下面這張圖,能夠加深大家對(duì)這個(gè)過(guò)程的理解。

一定掌握的JVM內(nèi)存管理知識(shí)都有什么

可以看到,程序計(jì)數(shù)器也是因?yàn)榫€程而產(chǎn)生的,與虛擬機(jī)棧配合完成計(jì)算操作。程序計(jì)數(shù)器還存儲(chǔ)了當(dāng)前正在運(yùn)行的流程,包括正在執(zhí)行的指令、跳轉(zhuǎn)、分支、循環(huán)、異常處理等。

我們可以看一下程序計(jì)數(shù)器里面的具體內(nèi)容。下面這張圖,就是使用 javap 命令輸出的字節(jié)碼。大家可以看到在每個(gè) opcode 前面,都有一個(gè)序號(hào)。就是圖中紅框中的偏移地址,你可以認(rèn)為它們是程序計(jì)數(shù)器的內(nèi)容。

一定掌握的JVM內(nèi)存管理知識(shí)都有什么

一定掌握的JVM內(nèi)存管理知識(shí)都有什么

堆是 JVM 上最大的內(nèi)存區(qū)域,我們申請(qǐng)的幾乎所有的對(duì)象,都是在這里存儲(chǔ)的。我們常說(shuō)的垃圾回收,操作的對(duì)象就是堆。

堆空間一般是程序啟動(dòng)時(shí),就申請(qǐng)了,但是并不一定會(huì)全部使用。

隨著對(duì)象的頻繁創(chuàng)建,堆空間占用的越來(lái)越多,就需要不定期的對(duì)不再使用的對(duì)象進(jìn)行回收。這個(gè)在 Java 中,就叫作 GC(Garbage Collection)。

由于對(duì)象的大小不一,在長(zhǎng)時(shí)間運(yùn)行后,堆空間會(huì)被許多細(xì)小的碎片占滿,造成空間浪費(fèi)。所以,僅僅銷毀對(duì)象是不夠的,還需要堆空間整理。這個(gè)過(guò)程非常的復(fù)雜。

那一個(gè)對(duì)象創(chuàng)建的時(shí)候,到底是在堆上分配,還是在棧上分配呢?這和兩個(gè)方面有關(guān):對(duì)象的類型和在 Java 類中存在的位置。

Java 的對(duì)象可以分為基本數(shù)據(jù)類型和普通對(duì)象。

對(duì)于普通對(duì)象來(lái)說(shuō),JVM 會(huì)首先在堆上創(chuàng)建對(duì)象,然后在其他地方使用的其實(shí)是它的引用。比如,把這個(gè)引用保存在虛擬機(jī)棧的局部變量表中。

對(duì)于基本數(shù)據(jù)類型來(lái)說(shuō)(byte、short、int、long、float、double、char),有兩種情況。

我們上面提到,每個(gè)線程擁有一個(gè)虛擬機(jī)棧。當(dāng)你在方法體內(nèi)聲明了基本數(shù)據(jù)類型的對(duì)象,它就會(huì)在棧上直接分配。其他情況,都是在堆上分配。

注意,像 int[] 數(shù)組這樣的內(nèi)容,是在堆上分配的。數(shù)組并不是基本數(shù)據(jù)類型。

一定掌握的JVM內(nèi)存管理知識(shí)都有什么

這就是 JVM 的基本的內(nèi)存分配策略。而堆是所有線程共享的,如果是多個(gè)線程訪問(wèn),會(huì)涉及數(shù)據(jù)同步問(wèn)題。

元空間

關(guān)于元空間,我們還是以一個(gè)非常高頻的面試題開(kāi)始:“為什么有 Metaspace 區(qū)域?它有什么問(wèn)題?”

說(shuō)到這里,你應(yīng)該回想一下類與對(duì)象的區(qū)別。對(duì)象是一個(gè)活生生的個(gè)體,可以參與到程序的運(yùn)行中;類更像是一個(gè)模版,定義了一系列屬性和操作。那么你可以設(shè)想一下。我們前面生成的 A.class,是放在 JVM 的哪個(gè)區(qū)域的?

想要問(wèn)答這個(gè)問(wèn)題,就不得不提下 Java 的歷史。在 Java 8 之前,這些類的信息是放在一個(gè)叫 Perm 區(qū)的內(nèi)存里面的。更早版本,甚至 String.intern 相關(guān)的運(yùn)行時(shí)常量池也放在這里。這個(gè)區(qū)域有大小限制,很容易造成 JVM 內(nèi)存溢出,從而造成 JVM 崩潰。

Perm 區(qū)在 Java 8 中已經(jīng)被徹底廢除,取而代之的是 Metaspace。原來(lái)的 Perm 區(qū)是在堆上的,現(xiàn)在的元空間是在非堆上的,這是背景。關(guān)于它們的對(duì)比,可以看下這張圖。

一定掌握的JVM內(nèi)存管理知識(shí)都有什么

然后,元空間的好處也是它的壞處。使用非堆可以使用操作系統(tǒng)的內(nèi)存,JVM 不會(huì)再出現(xiàn)方法區(qū)的內(nèi)存溢出;但是,無(wú)限制的使用會(huì)造成操作系統(tǒng)的死亡。所以,一般也會(huì)使用參數(shù) -XX:MaxMetaspaceSize 來(lái)控制大小。

方法區(qū),作為一個(gè)概念,依然存在。它的物理存儲(chǔ)的容器,就是 Metaspace。現(xiàn)在,只需要了解到,這個(gè)區(qū)域存儲(chǔ)的內(nèi)容,包括:類的信息、常量池、方法數(shù)據(jù)、方法代碼就可以了。

小結(jié)

  •  我們常說(shuō)的字符串常量,存放在哪呢?

由于常量池,在 Java 7 之后,放到了堆中,我們創(chuàng)建的字符串,將會(huì)在堆上分配。

  •  堆、非堆、本地內(nèi)存,有什么關(guān)系?

關(guān)于它們的關(guān)系,我們可以看一張圖。在我的感覺(jué)里,堆是軟綿綿的,松散而有彈性;而非堆是冰冷生硬的,內(nèi)存非常緊湊。

一定掌握的JVM內(nèi)存管理知識(shí)都有什么

大家都知道,JVM 在運(yùn)行時(shí),會(huì)從操作系統(tǒng)申請(qǐng)大塊的堆內(nèi)內(nèi)存,進(jìn)行數(shù)據(jù)的存儲(chǔ)。但是,堆外內(nèi)存也就是申請(qǐng)后操作系統(tǒng)剩余的內(nèi)存,也會(huì)有部分受到 JVM 的控制。比較典型的就是一些 native 關(guān)鍵詞修飾的方法,以及對(duì)內(nèi)存的申請(qǐng)和處理。

在 Linux 機(jī)器上,使用 top 或者 ps 命令,在大多數(shù)情況下,能夠看到 RSS 段(實(shí)際的內(nèi)存占用),是大于給 JVM 分配的堆內(nèi)存的。

如果你申請(qǐng)了一臺(tái)系統(tǒng)內(nèi)存為 2GB 的主機(jī),可能 JVM 能用的就只有 1GB,這便是一個(gè)限制。

JVM 的運(yùn)行時(shí)區(qū)域是棧,而存儲(chǔ)區(qū)域是堆。很多變量,其實(shí)在編譯期就已經(jīng)固定了。

以上就是一定掌握的JVM內(nèi)存管理知識(shí)都有什么,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

標(biāo)題名稱:一定掌握的JVM內(nèi)存管理知識(shí)都有什么
當(dāng)前網(wǎng)址:http://muchs.cn/article40/ihpoho.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站制作、域名注冊(cè)Google、網(wǎng)站策劃做網(wǎng)站、網(wǎng)站改版

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營(yíng)