亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Java 內(nèi)存區(qū)域詳解

darry / 2884人閱讀

摘要:三對象的內(nèi)存布局對象在堆中的布局分為三個區(qū)域?qū)ο箢^,實(shí)例數(shù)據(jù),對齊填充??偨Y(jié)了解內(nèi)存區(qū)域是對的深入學(xué)習(xí),以前只知道有堆和棧的區(qū)分,現(xiàn)在我們了解到了具體的堆棧的作用。

引言

學(xué)習(xí)Java也有一段時間了,總感覺有些東西學(xué)的不是很精通。例如Java內(nèi)存區(qū)域到底是怎么樣的?程序是怎么跑的?對象是怎么存放的?這些都影響了我對自己的程序運(yùn)行的熟悉程度。

一. 運(yùn)行時數(shù)據(jù)區(qū)域

Java虛擬機(jī)在執(zhí)行java程序的過程中,會把它所管理的內(nèi)存劃分成若干個不同的數(shù)據(jù)區(qū)域(每當(dāng)運(yùn)行一個java程序都會啟動一個虛擬機(jī))。有一本書叫做《Java虛擬機(jī)規(guī)范》,講述了Sun公司對Java虛擬機(jī)實(shí)現(xiàn)的相關(guān)規(guī)范,其中講了虛擬機(jī)將所管理的內(nèi)存分為以下幾個部分:

程序計(jì)數(shù)器
虛擬機(jī)棧

本地方法區(qū)

方法區(qū)

其中方法區(qū)和堆是由所有線程共享的,例如使用ThreadPoolExecutor創(chuàng)建多個線程時,堆與方法區(qū)都可以被多個線程讀取。

程序計(jì)數(shù)器 學(xué)過計(jì)算機(jī)組成原理的人都會知道在CPU的寄存器中有一個PC寄存器,存放下一條指令地址,這里,虛擬機(jī)不使用CPU的程序計(jì)數(shù)器,自己在內(nèi)存中設(shè)立一片區(qū)域來模擬CPU的程序計(jì)數(shù)器。只有一個程序計(jì)數(shù)器是不夠的,當(dāng)多個線程切換執(zhí)行時,那就單個程序計(jì)數(shù)器就沒辦法了,虛擬機(jī)規(guī)范中指出,每一條線程都有一個獨(dú)立的程序計(jì)數(shù)器。注意,Java虛擬機(jī)中的程序計(jì)數(shù)器指向正在執(zhí)行的字節(jié)碼地址,而不是下一條。

虛擬機(jī)棧線程私有的,它的生命周期與線程相同。虛擬機(jī)棧描述的是Java方法執(zhí)行的內(nèi)存模型:每個方法執(zhí)行的時候都會創(chuàng)建一個棧幀(我覺得可以把它看作是一個快照,記錄下進(jìn)入方法前的一些參數(shù),實(shí)際上是方法運(yùn)行時的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)),用于存放局部變量表,操作數(shù)棧,動態(tài)鏈接,方法出口等信息。每一個方法從調(diào)用直到執(zhí)行完成的過程都對應(yīng)著一個棧幀在虛擬機(jī)中的入棧到出棧的過程。我們平時把內(nèi)存分為堆內(nèi)存和棧內(nèi)存,其中的棧內(nèi)存就指的是虛擬機(jī)棧的局部變量表部分。局部變量表存放了編譯期可以知道的基本數(shù)據(jù)類型,對象引用,和返回后所指向的字節(jié)碼的地址。

本地方法區(qū)虛擬機(jī)棧 所發(fā)揮的作用很類似,但是要注意一下,虛擬機(jī)規(guī)范中沒有對本地方法區(qū)中的方法作強(qiáng)制規(guī)定,虛擬機(jī)可以自由實(shí)現(xiàn),即可以不是字節(jié)碼。但是也可以是字節(jié)碼,這樣虛擬機(jī)棧和本地方法區(qū)就可以合二為一,事實(shí)上,OpenJDKSunJDK所自帶的HotSpot虛擬機(jī)就直接將虛擬機(jī)棧和本地方法區(qū)合二為一。

這個概念應(yīng)該很多人都很熟悉,例如初學(xué)C語言的時候,老師就會講malloc方法會在堆中分配空間,這里也一樣。這個區(qū)域是用來存放對象實(shí)例的,幾乎所有對象實(shí)例都會在這里分配內(nèi)存,虛擬機(jī)規(guī)范中講:所有對象的實(shí)例以及數(shù)組都要在堆上分配。但是隨著JIT(Just-in-time) 編譯期的發(fā)展,有些時候也有可能在棧上分配(這里我也不是很明白其中的道理)。堆是java垃圾收集器管理的主要區(qū)域(很多時候會稱為GC堆,不叫垃圾堆),垃圾收集器實(shí)現(xiàn)了對象的自動銷毀。

方法區(qū) 也是各個線程共享的區(qū)域,它用于存儲已經(jīng)被虛擬機(jī)加載過的類信息,常量,靜態(tài)變量,及時編譯期編譯后的代碼(類方法)等數(shù)據(jù)。這里要講一下運(yùn)行時常量池,它是方法區(qū)的一部分,用于存放編譯期生成的各種字面量和符號引用(其實(shí)就是八大基本類型的包裝類型和String類型數(shù)據(jù))。

最后還有一個直接內(nèi)存,在JDK1.4版本中加入了NIO類,引入了基于通道(Channel)與緩沖區(qū)(Buffer)的I/O方式,也就是說通過這種方式,不會在運(yùn)行時數(shù)據(jù)區(qū)域分配內(nèi)存,這樣就避免了在運(yùn)行時數(shù)據(jù)區(qū)域來回復(fù)制數(shù)據(jù),直接調(diào)用外部內(nèi)存。

二. 對象的創(chuàng)建

對于面向?qū)ο蟮囊婚T語言,我們無時不在通過new關(guān)鍵字創(chuàng)建對象,那么這個過程又是怎樣的呢?

當(dāng)虛擬機(jī)遇到一條new指令的時候,首先會去檢查所new的類是否已經(jīng)被加載,在哪里檢查?當(dāng)然在方法區(qū),方法區(qū)存放了加載過的類信息。如果沒有加載,那么先執(zhí)行類的加載。

通過類加載檢查后,虛擬機(jī)開始為新生對象分配內(nèi)存,對象所需要的內(nèi)存大小在類加載完成后已經(jīng)可以確定,這時候只要在堆中分配空間即可。分配內(nèi)存有兩種方式,第一種,我們假設(shè)內(nèi)存絕對規(guī)整,那么只要在用過的內(nèi)存和沒用過的內(nèi)存間放置一個指針即可,每次分配空間的時候只要把指針向空閑空間移動相應(yīng)距離即可。第二種,我們假設(shè)空閑內(nèi)存和非空閑內(nèi)存夾雜在一起,實(shí)際上就是這種情況,那么就需要一個列表,去記錄堆內(nèi)存的使用情況,操作系統(tǒng)對內(nèi)存的管理就是這樣的。

那么,我們還要考慮一個問題,即在多線程的情況下,只有一個指針怎么能確保一個線程分配了內(nèi)存指針沒修改的時候另一個線程又分配內(nèi)存不會覆蓋之前的內(nèi)存呢?這里有一種方法,讓每一個線程在堆中先預(yù)分配一小塊內(nèi)存(TLAB本地線程分配緩沖),每個線程只在自己的內(nèi)存中分配內(nèi)存。

最后,對象被成功分配內(nèi)存。我們知道通過一個對象,我們可以通過getClass()方法獲取類,默認(rèn)比較兩個對象實(shí)際比較的是對象內(nèi)存的哈希值,這又是怎么實(shí)現(xiàn)的呢?其實(shí)在分配完內(nèi)存后,虛擬機(jī)會對對象進(jìn)行必要的設(shè)置,對象的類,對象的哈希碼等信息都存放在對象的對象頭中,所以分配的內(nèi)存大小絕不止屬性的總和。

三. 對象的內(nèi)存布局

對象在堆中的布局分為三個區(qū)域:對象頭實(shí)例數(shù)據(jù),對齊填充

對象頭 包括兩個部分,第一部分用于存儲自身運(yùn)行時的數(shù)據(jù)例如GC標(biāo)志位,MonirGC次數(shù),哈希碼,鎖狀態(tài),哪個線程可以擁有等被稱為MarkWord(標(biāo)記字)。第二部分存放指向方法區(qū)類數(shù)據(jù)的指針。在32位系統(tǒng)中,class指針大小為4字節(jié),標(biāo)記字大小為4字節(jié)。在64位系統(tǒng)中標(biāo)記字大小為8字節(jié)。

實(shí)例數(shù)據(jù) 存放類的屬性信息,包括父類的屬性信息。數(shù)組的實(shí)例部分還包括數(shù)組的長度。實(shí)例信息按類分別4字節(jié)對齊。

對齊填充 這是虛擬機(jī)要求對象起始地址必須是8字節(jié)的整數(shù)倍,可以說對齊填充沒有什么特別的含義。

四. 對象的訪問定位

我們知道,引用是引用,對象實(shí)例是對象實(shí)例。引用存放在虛擬機(jī)棧中,數(shù)據(jù)類型為reference,對象實(shí)例存放在堆中。那么引用是如何指向?qū)ο髮?shí)例的呢?

主流的訪問方式有兩種,第一種是通過句柄池,如果使用句柄池,那么java堆中將會劃分出一部分內(nèi)存作為句柄池,句柄包含對象類型指針指向方法區(qū)的類型信息,還有對象實(shí)例指針,指向堆中的實(shí)例地址。

第二種是reference引用直接指向堆中的對象實(shí)例,對象實(shí)例的對象頭存放對象類型指針。

兩種方法各有優(yōu)勢,第一種可以在對象實(shí)例在GC時移動的時候只改變句柄池中的對象實(shí)例指針,而不用改變reference引用本身。第二種方法就是訪問速度快,減少了一次指針定位的時間開銷。目前HotSpot虛擬機(jī)就采用的第二種方式。

總結(jié)

了解java內(nèi)存區(qū)域是對java的深入學(xué)習(xí),以前只知道有堆和棧的區(qū)分,現(xiàn)在我們了解到了具體的堆棧的作用。內(nèi)存是怎么劃分的,對象是怎么存儲的,方法和屬性的存放區(qū)別。通過對這些內(nèi)容的了解,會讓我們寫java程序更加游刃有余,有的放矢。
更多文章:http://blog.gavinzh.com

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/64374.html

相關(guān)文章

  • JVM系列(一):深入詳解JVM 內(nèi)存區(qū)域總結(jié)!

    摘要:一內(nèi)存區(qū)域虛擬機(jī)在運(yùn)行時,會把內(nèi)存空間分為若干個區(qū)域,根據(jù)虛擬機(jī)規(guī)范版的規(guī)定,虛擬機(jī)所管理的內(nèi)存區(qū)域分為如下部分方法區(qū)堆內(nèi)存虛擬機(jī)棧本地方法棧程序計(jì)數(shù)器。前言 在JVM的管控下,Java程序員不再需要管理內(nèi)存的分配與釋放,這和在C和C++的世界是完全不一樣的。所以,在JVM的幫助下,Java程序員很少會關(guān)注內(nèi)存泄露和內(nèi)存溢出的問題。但是,一旦JVM發(fā)生這些情況的時候,如果你不清楚JVM內(nèi)存的...

    Aldous 評論0 收藏0
  • JVM虛擬機(jī)詳解

    摘要:虛擬機(jī)包括一套字節(jié)碼指令集一組寄存器一個棧一個垃圾回收堆和一個存儲方法域。而使用虛擬機(jī)是實(shí)現(xiàn)這一特點(diǎn)的關(guān)鍵。虛擬機(jī)在執(zhí)行字節(jié)碼時,把字節(jié)碼解釋成具體平臺上的機(jī)器指令執(zhí)行。此內(nèi)存區(qū)域是唯一一個在虛擬機(jī)規(guī)范中沒有規(guī)定任何情況的區(qū)域。 1、 什么是JVM?   JVM是Java Virtual Machine(Java虛擬機(jī))的縮寫,JVM是一種用于計(jì)算設(shè)備的規(guī)范,它是一個虛構(gòu)出來的計(jì)算機(jī),...

    rottengeek 評論0 收藏0
  • JAVA GC 原理詳解

    摘要:虛擬機(jī)棧區(qū)也就是通常所說的棧區(qū),它描述的是方法執(zhí)行的內(nèi)存模型,每個方法被執(zhí)行的時候都創(chuàng)建一個棧幀,用于存儲局部變量表操作數(shù)棧動態(tài)鏈接方法出口等。每個方法被調(diào)用到完成,相當(dāng)于一個棧幀在虛擬機(jī)棧中從入棧到出棧的過程。 大多數(shù)情況下我們對GC的了解都只是淺層含義上的,下面我們來詳細(xì)講解下內(nèi)部的一些實(shí)現(xiàn)原理。講解GC之前,我們得先了解下JVM的內(nèi)存結(jié)構(gòu),才能讓我們理解GC導(dǎo)致是干嘛的。 一.J...

    wangjuntytl 評論0 收藏0
  • JVM詳解1.Java內(nèi)存模型

    摘要:編譯參見深入理解虛擬機(jī)節(jié)走進(jìn)之一自己編譯源碼內(nèi)存模型運(yùn)行時數(shù)據(jù)區(qū)域根據(jù)虛擬機(jī)規(guī)范的規(guī)定,的內(nèi)存包括以下幾個運(yùn)運(yùn)行時數(shù)據(jù)區(qū)域程序計(jì)數(shù)器程序計(jì)數(shù)器是一塊較小的內(nèi)存空間,他可以看作是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號指示器。 點(diǎn)擊進(jìn)入我的博客 1.1 基礎(chǔ)知識 1.1.1 一些基本概念 JDK(Java Development Kit):Java語言、Java虛擬機(jī)、Java API類庫JRE(...

    TANKING 評論0 收藏0
  • 四年來Android面試大綱,作為一個Android程序員

    摘要:再附一部分架構(gòu)面試視頻講解本文已被開源項(xiàng)目學(xué)習(xí)筆記總結(jié)移動架構(gòu)視頻大廠面試真題項(xiàng)目實(shí)戰(zhàn)源碼收錄 Java反射(一)Java反射(二)Java反射(三)Java注解Java IO(一)Java IO(二)RandomAccessFileJava NIOJava異常詳解Java抽象類和接口的區(qū)別Java深拷貝和淺拷...

    不知名網(wǎng)友 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<