成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Java內(nèi)存區(qū)域劃分和內(nèi)存分配

BDEEFE / 3494人閱讀

摘要:運(yùn)行時(shí)數(shù)據(jù)區(qū)域虛擬機(jī)在執(zhí)行的過程中會(huì)把管理的內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)域。方法區(qū)的內(nèi)存收集還是會(huì)出現(xiàn),不過這個(gè)區(qū)域的內(nèi)存收集主要是針對(duì)常量池的回收和對(duì)類型的卸載。當(dāng)方法區(qū)無法滿足內(nèi)存分配需求時(shí)將拋出異常。

運(yùn)行時(shí)數(shù)據(jù)區(qū)域
Java虛擬機(jī)在執(zhí)行Java的過程中會(huì)把管理的內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)域。這些區(qū)域有各自的用途,以及創(chuàng)建和銷毀的時(shí)間,有的區(qū)域隨著虛擬機(jī)進(jìn)程的啟動(dòng)而存在,而有的區(qū)域則依賴線程的啟動(dòng)和結(jié)束而創(chuàng)建和銷毀。

程序計(jì)數(shù)器
程序計(jì)數(shù)器是一塊較小的區(qū)域,它的作用可以看做是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器。在虛擬機(jī)的模型里,字節(jié)碼指示器就是通過改變程序計(jì)數(shù)器的值來指定下一條需要執(zhí)行的指令。分支,循環(huán)等基礎(chǔ)功能就是依賴程序計(jì)數(shù)器來完成的。

由于java虛擬機(jī)的多線程是通過輪流切換并分配處理器執(zhí)行時(shí)間來完成,一個(gè)處理器同一時(shí)間只會(huì)執(zhí)行一條線程中的指令。為了線程恢復(fù)后能夠恢復(fù)正確的執(zhí)行位置,每條線程都需要一個(gè)獨(dú)立的程序計(jì)數(shù)器,以確保線程之間互不影響。所以程序計(jì)數(shù)器是“線程私有”的內(nèi)存。

如果虛擬機(jī)正在執(zhí)行的是一個(gè)Java方法,則計(jì)數(shù)器指定的是字節(jié)碼指令對(duì)應(yīng)的地址,如果正在執(zhí)行的是一個(gè)本地方法,則計(jì)數(shù)器指定問空undefined。程序計(jì)數(shù)器區(qū)域是Java虛擬機(jī)中唯一沒有定義OutOfMemory異常的區(qū)域。

Java虛擬機(jī)棧
他和程序計(jì)數(shù)器一樣也是線程私有的,生命周期與線程相同。虛擬機(jī)棧描述的是Java方法執(zhí)行的內(nèi)存模型:每個(gè)方法被執(zhí)行的時(shí)候都會(huì)創(chuàng)建一個(gè)棧幀用于存儲(chǔ)局部變量表,操作棧,動(dòng)態(tài)鏈接,方法出口等信息。每一個(gè)方法被調(diào)用的過程就對(duì)應(yīng)一個(gè)棧幀在虛擬機(jī)棧中從入棧到出棧的過程。

通常所說的虛擬機(jī)運(yùn)行時(shí)分為棧和堆,這里的棧指的就是虛擬機(jī)?;蛘哒f虛擬機(jī)棧中的局部變量表部分。

局部變量表存放了編譯器可知的各種基本數(shù)據(jù)類型、對(duì)象引用和returnAddress類型(指向一條字節(jié)碼指令的地址)。局部變量表所需的內(nèi)存空間在編譯器完成分配,當(dāng)進(jìn)入一個(gè)方法時(shí)這個(gè)方法需要在幀中分配多大的內(nèi)存空間是完全確定的,運(yùn)行期間不會(huì)改變局部變量表的大小。(64為長(zhǎng)度的long和double會(huì)占用兩個(gè)局部變量空間,其他的數(shù)據(jù)類型占用一個(gè))

Java虛擬機(jī)??赡艹霈F(xiàn)兩種類型的異常:1. 線程請(qǐng)求的棧深度大于虛擬機(jī)允許的棧深度,將拋出StackOverflowError。2.虛擬機(jī)??臻g可以動(dòng)態(tài)擴(kuò)展,當(dāng)動(dòng)態(tài)擴(kuò)展是無法申請(qǐng)到足夠的空間時(shí),拋出OutOfMemory異常。

本地方法棧
本地方法棧和虛擬機(jī)?;绢愃疲徊贿^Java虛擬機(jī)棧執(zhí)行的是Java代碼(字節(jié)碼),本地方法棧中執(zhí)行的是本地方法的服務(wù)。本地方法棧中也會(huì)拋出StackOverflowError和OutOfMemory異常。

堆是Java虛擬機(jī)所管理的內(nèi)存中最大的一塊。堆是所有線程共享的一塊區(qū)域,在虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建。堆的唯一目的是存放對(duì)象實(shí)例,幾乎所有的對(duì)象實(shí)例都在這里分配,不過隨著JIT編譯器的發(fā)展和逃逸技術(shù)的成熟,棧上分配和標(biāo)量替換技術(shù)使得這種情況發(fā)生著微妙的變化,對(duì)上分配正變得不那么絕對(duì)。
附:在Java編程語言和環(huán)境中,即時(shí)編譯器(JIT compiler,just-in-time compiler)是一個(gè)把Java的字節(jié)碼(包括需要被解釋的指令的程序)轉(zhuǎn)換成可以直接發(fā)送給處理器的指令的程序。當(dāng)你寫好一個(gè)Java程序后,源語言的語句將由Java編譯器編譯成字節(jié)碼,而不是編譯成與某個(gè)特定的處理器硬件平臺(tái)對(duì)應(yīng)的指令代碼(比如,Intel的Pentium微處理器或IBM的System/390處理器)。字節(jié)碼是可以發(fā)送給任何平臺(tái)并且能在那個(gè)平臺(tái)上運(yùn)行的獨(dú)立于平臺(tái)的代碼。

Java堆是垃圾收集器管理的主要區(qū)域,所以也稱為“GC堆”。由于現(xiàn)在的垃圾收集器基本上都是采用分代收集算法,所以Java堆還可細(xì)分為:新生代和老生代。在細(xì)致一點(diǎn)可分為Eden空間,F(xiàn)rom Survivor空間,To Survivor空間。如果從內(nèi)存分配的角度看,線程共享的Java堆可劃分出多個(gè)線程私有的分配緩沖區(qū)。不過無論如何劃分,都與存放內(nèi)容無關(guān),無論哪個(gè)區(qū)域,都是用來存放對(duì)象實(shí)例。細(xì)分的目的是為了更好的回收內(nèi)存或者更快的分配內(nèi)存。

Java堆可以是物理上不連續(xù)的空間,只要邏輯上連續(xù)即可,主流的虛擬機(jī)都是按照可擴(kuò)展的方式來實(shí)現(xiàn)的。如果當(dāng)前堆中沒有內(nèi)存完成對(duì)象實(shí)例的創(chuàng)建,并且不能在進(jìn)行內(nèi)存擴(kuò)展,則會(huì)拋出OutOfMemory異常。

方法區(qū)

方法區(qū)也是線程共享的區(qū)域,用于存儲(chǔ)已經(jīng)被虛擬機(jī)加載的類信息,常量,靜態(tài)變量和即時(shí)編譯器(JIT)編譯后的代碼等數(shù)據(jù)。Java虛擬機(jī)把方法區(qū)描述為堆的一個(gè)邏輯分區(qū),不過方法區(qū)有一個(gè)別名Non-Heap(非堆),用于區(qū)別于Java堆區(qū)。

Java虛擬機(jī)規(guī)范對(duì)這個(gè)區(qū)域的限制也非常寬松,除了可以是物理不連續(xù)的空間外,也允許固定大小和擴(kuò)展性,還可以不實(shí)現(xiàn)垃圾收集。相對(duì)而言,垃圾收集行為在這個(gè)區(qū)域是比較少出現(xiàn)的(所以常量和靜態(tài)變量的定義要多注意)。方法區(qū)的內(nèi)存收集還是會(huì)出現(xiàn),不過這個(gè)區(qū)域的內(nèi)存收集主要是針對(duì)常量池的回收和對(duì)類型的卸載。
一般來說方法區(qū)的內(nèi)存回收比較難以令人滿意。當(dāng)方法區(qū)無法滿足內(nèi)存分配需求時(shí)將拋出OutOfMemoryError異常。

運(yùn)行時(shí)常量池

運(yùn)行時(shí)常量池是方法區(qū)的一部分,Class文件中除了有類的版本,字段,方法,接口等信息以外,還有一項(xiàng)信息是常量池用于存儲(chǔ)編譯器生成的各種字面量和符號(hào)引用,這部分信息將在類加載后存放到方法區(qū)的運(yùn)行時(shí)常量池中。Java虛擬機(jī)對(duì)類的每一部分(包括常量池)都有嚴(yán)格的規(guī)定,每個(gè)字節(jié)用于存儲(chǔ)哪種數(shù)據(jù)都必須有規(guī)范上的要求,這樣才能夠被虛擬機(jī)認(rèn)可,裝載和執(zhí)行。一般來說,除了保存Class文件中描述的符號(hào)引用外,還會(huì)把翻譯出來的直接引用也存儲(chǔ)在運(yùn)行時(shí)常量池中。

    運(yùn)行時(shí)常量池相對(duì)于Class文件常量池的另外一個(gè)重要特征是具備動(dòng)態(tài)性,Java虛擬機(jī)并不要求常量只能在編譯期產(chǎn)生,也就是并非預(yù)置入Class文件常量池的內(nèi)容才能進(jìn)入方法區(qū)的運(yùn)行時(shí)常量池中,運(yùn)行期間也可將新的常量放入常量池中。

   常量池是方法區(qū)的一部分,所以受到內(nèi)存的限制,當(dāng)無法申請(qǐng)到足夠內(nèi)存時(shí)會(huì)拋出OutOfMemoryError異常。
   

對(duì)象訪問

對(duì)象訪問在Java語言中無處不在,即使是最簡(jiǎn)單的訪問,也會(huì)涉及到Java棧,java堆,方法區(qū)這三個(gè)最重要的內(nèi)存區(qū)域之間的關(guān)聯(lián)關(guān)系。如下面的代碼:

Object obj = new Object();

   假設(shè)這段代碼出現(xiàn)在方法體中,那么“Object obj”部分的語義將會(huì)反映到Java棧的本地變量表中,作為一個(gè)reference類型的數(shù)據(jù)存在。而“new Object();”部分的語義將會(huì)反應(yīng)到Java堆中,形成一塊存儲(chǔ)Object類型所有實(shí)例數(shù)據(jù)值(Instance Data)的結(jié)構(gòu)化內(nèi)存,根據(jù)具體類型以及虛擬機(jī)實(shí)現(xiàn)的對(duì)象分布的不同,這塊內(nèi)存的長(zhǎng)度是不固定的。另外,在JAVA堆中還必須包含能查找到此對(duì)象內(nèi)存數(shù)據(jù)的地址信息,這些類型數(shù)據(jù)則存儲(chǔ)在方法區(qū)中。
   

由于reference類型在Java虛擬機(jī)中之規(guī)定了指向?qū)ο蟮囊?,并沒有規(guī)定這個(gè)引用要通過哪種方式去定位,以及訪問到Java堆中的對(duì)象的具體位置,因此虛擬機(jī)實(shí)現(xiàn)的對(duì)象訪問方式會(huì)有所不同。主流的訪問方式有兩種:句柄訪問方式和直接指針。

如果使用句柄訪問方式,Java堆中將會(huì)劃分出一塊內(nèi)存來作為句柄池,reference中存儲(chǔ)的就是對(duì)象的地址,而句柄中包含了對(duì)象實(shí)例數(shù)據(jù)和類型數(shù)據(jù)各自的具體地址信息。

如果通過直接指針方式訪問,Java堆對(duì)象的布局中就必須考慮如何放置訪問類型數(shù)據(jù)的相關(guān)信息,reference中直接存儲(chǔ)的就是對(duì)象的地址。

兩種方式各有優(yōu)勢(shì),局部訪問方式最大的好處是reference中存放的是穩(wěn)定的句柄地址,在對(duì)象被移動(dòng)時(shí),只會(huì)改變句柄中的實(shí)例數(shù)據(jù)指針,而reference本身不需要被修改。而指針訪問的最大優(yōu)勢(shì)是速度快,它節(jié)省了一次指針定位的開銷,由于對(duì)象訪問在Java中非常頻繁,一次這類開銷積少成多后也是一項(xiàng)非??捎^的成本。

    具體的訪問方式都是有虛擬機(jī)指定的,虛擬機(jī)Sun HotSpot使用的是直接指針方式,不過從整個(gè)軟件開發(fā)的范圍來看,各種語言和框架使用句柄訪問方式的情況十分常見。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/64754.html

相關(guān)文章

  • JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)

    摘要:運(yùn)行時(shí)數(shù)據(jù)區(qū)域之所以要?jiǎng)澐诌@么多區(qū)域出來是因?yàn)檫@些區(qū)域都有自己的用途,以及創(chuàng)建和銷毀的時(shí)間。,運(yùn)行時(shí)常量池它是方法區(qū)的一部分。直接內(nèi)存直接內(nèi)存并不是虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)的一部分,也不是虛擬機(jī)規(guī)范中定義的內(nèi)存區(qū)域。 前言 說到JAVA內(nèi)存區(qū)域,可能很多人第一反應(yīng)是堆棧。首先,堆棧不是一個(gè)概念,而是兩個(gè)概念,堆和棧是兩塊不同的內(nèi)存區(qū)域,簡(jiǎn)單理解的話,堆是用來存放對(duì)象而棧是用來運(yùn)行程序的。其次...

    Loong_T 評(píng)論0 收藏0
  • 深入理解Java虛擬機(jī)(自動(dòng)內(nèi)存管理機(jī)制)

    摘要:看來還是功力不夠,索性拆成了六篇文章,分別從自動(dòng)內(nèi)存管理機(jī)制類文件結(jié)構(gòu)類加載機(jī)制字節(jié)碼執(zhí)行引擎程序編譯與代碼優(yōu)化高效并發(fā)六個(gè)方面來做更加細(xì)致的介紹。本文先說說虛擬機(jī)的自動(dòng)內(nèi)存管理機(jī)制。在類加載檢查通過后,虛擬機(jī)將為新生對(duì)象分配內(nèi)存。 歡迎關(guān)注微信公眾號(hào):BaronTalk,獲取更多精彩好文! 書籍真的是常讀常新,古人說「書讀百遍其義自見」還是蠻有道理的。周志明老師的這本《深入理解 Ja...

    yck 評(píng)論0 收藏0
  • 《深入理解java虛擬機(jī)》學(xué)習(xí)筆記系列——java內(nèi)存區(qū)域劃分

    摘要:運(yùn)行時(shí)數(shù)據(jù)區(qū)域的學(xué)習(xí),是學(xué)習(xí)以及機(jī)制的基礎(chǔ),也是深入理解對(duì)象創(chuàng)建及運(yùn)行過程的前提。了解內(nèi)存區(qū)域劃分,是學(xué)習(xí)概念的前提。 Java 運(yùn)行時(shí)數(shù)據(jù)區(qū)域的學(xué)習(xí),是學(xué)習(xí) jvm 以及 GC 機(jī)制的基礎(chǔ),也是深入理解 java 對(duì)象創(chuàng)建及運(yùn)行過程的前提。廢話不多說,直接進(jìn)入正題: 一張圖總結(jié) showImg(https://segmentfault.com/img/bVOMAn?w=685&h=5...

    史占廣 評(píng)論0 收藏0
  • jvm基礎(chǔ)篇一之內(nèi)存區(qū)域

    摘要:堆區(qū)堆是虛擬機(jī)所管理的內(nèi)存中最大的一塊,它是被所有線程共享的一塊內(nèi)存區(qū)域,該區(qū)域在虛擬機(jī)啟動(dòng)的時(shí)候創(chuàng)建。 運(yùn)行時(shí)數(shù)據(jù)區(qū)域 ? ?想要了解jvm,那對(duì)其內(nèi)存分配管理的學(xué)習(xí)是必不可少的;java虛擬機(jī)在執(zhí)行java程序的時(shí)候會(huì)把它所管理的內(nèi)存劃分成若干數(shù)據(jù)區(qū)域。這些區(qū)域有著不同的功能、用途、創(chuàng)建/銷毀時(shí)間。java虛擬機(jī)所分配管理的內(nèi)存區(qū)域如圖1所示 程序計(jì)數(shù)器 ? ?程序計(jì)數(shù)器是一塊比較...

    Zachary 評(píng)論0 收藏0
  • 深入理解虛擬機(jī)之Java內(nèi)存區(qū)域

    摘要:深入理解虛擬機(jī)高級(jí)特性與最佳實(shí)踐第二版讀書筆記與常見面試題總結(jié)本節(jié)常見面試題介紹下內(nèi)存區(qū)域運(yùn)行時(shí)數(shù)據(jù)區(qū)。運(yùn)行時(shí)數(shù)據(jù)區(qū)域虛擬機(jī)在執(zhí)行程序的過程中會(huì)把它管理的內(nèi)存劃分成若干個(gè)不同的數(shù)據(jù)區(qū)域。 《深入理解Java虛擬機(jī):JVM高級(jí)特性與最佳實(shí)踐(第二版》讀書筆記與常見面試題總結(jié) 本節(jié)常見面試題: 介紹下Java內(nèi)存區(qū)域(運(yùn)行時(shí)數(shù)據(jù)區(qū))。 對(duì)象的訪問定位的兩種方式。 1 概述 對(duì)于Java...

    lavnFan 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<