1.1方法區(qū):方法區(qū)是系統(tǒng)分配的一個(gè)內(nèi)存邏輯區(qū)域,是JVM在裝載類(lèi)文件時(shí),用于存儲(chǔ)類(lèi)型信息的(類(lèi)的描述信息)。方法區(qū)存放的信息包括:1.1.1類(lèi)的基本信息:每個(gè)類(lèi)的全限定名每個(gè)類(lèi)的直接超類(lèi)的全限定名(可約束類(lèi)型轉(zhuǎn)換)" />

亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Java中運(yùn)行時(shí)內(nèi)存結(jié)構(gòu)補(bǔ)充

系統(tǒng) 2796 0

Java中運(yùn)行時(shí)內(nèi)存結(jié)構(gòu)

<wbr><wbr></wbr></wbr> 1.1 方法區(qū): <wbr></wbr>

方法區(qū)是系統(tǒng)分配的一個(gè)內(nèi)存邏輯區(qū)域,是 JVM 在裝載類(lèi)文件時(shí),用于存儲(chǔ)類(lèi)型信息的 ( 類(lèi)的描述信息 )。

<wbr></wbr>

方法區(qū)存放的信息包括:

<wbr><wbr><wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr></wbr></wbr> 1.1.1 類(lèi)的基本信息:

  1. 每個(gè)類(lèi)的全限定名
  2. 每個(gè)類(lèi)的直接超類(lèi)的全限定名 ( 可約束類(lèi)型轉(zhuǎn)換 )
  3. 該類(lèi)是類(lèi)還是接口
  4. 該類(lèi)型的訪問(wèn)修飾符
  5. 直接超接口的全限定名的有序列表

<wbr><wbr><wbr><wbr><wbr><wbr><wbr>1.1.2<strong>已裝載類(lèi)的詳細(xì)信息</strong>:</wbr></wbr></wbr></wbr></wbr></wbr></wbr>

  1. <wbr><span style="word-wrap:normal; word-break:normal; color:rgb(255,0,0)">運(yùn)行時(shí)常量池</span>:</wbr>

    在方法區(qū)中,每個(gè)類(lèi)型都對(duì)應(yīng)一個(gè)常量池,存放該類(lèi)型所用到的所有常量,常量池中存儲(chǔ)了諸如 文字字符串、 final 變量值、類(lèi)名和方法名常量。 它們以數(shù)組形式通過(guò)索引被訪問(wèn),是外部調(diào)用與類(lèi)聯(lián)系及類(lèi)型對(duì)象化的橋梁。(存的可能是個(gè)普通的字符串,然后經(jīng)過(guò)常量池解析,則變成指向某個(gè)類(lèi)的引用)

  2. <wbr><span style="word-wrap:normal; word-break:normal; color:rgb(255,0,0)">字段信息</span>:</wbr>

    字段信息存放類(lèi)中聲明的每一個(gè)字段的信息,包括字段的名、類(lèi)型、修飾符。

    字段名稱(chēng)指的是類(lèi)或接口的實(shí)例變量或類(lèi)變量,字段的描述符是一個(gè)指示字段的類(lèi)型的字符串,如 private A a=null; a 為字段名, A 為描述符, private 為修飾符

  3. <wbr><span style="word-wrap:normal; word-break:normal; color:rgb(255,0,0)">方法信息</span>:</wbr>

    類(lèi)中聲明的每一個(gè)方法的信息,包括方法名、返回值類(lèi)型、參數(shù)類(lèi)型、修飾符、異常、方法的字節(jié)碼。

    (在編譯的時(shí)候,就已經(jīng)將方法的局部變量、操作數(shù)棧大小等確定并存放在字節(jié)碼中,在裝載的時(shí)候,隨著類(lèi)一起裝入方法區(qū) 。)

    在運(yùn)行時(shí),JVM從常量池中獲得符號(hào)引用,然后在運(yùn)行時(shí)解析成引用項(xiàng)的實(shí)際地址,最后通過(guò)常量池中的全限定名、方法和字段描述符,把當(dāng)前類(lèi)或接口中的代碼與其它類(lèi)或接口中的代碼聯(lián)系起來(lái)。
  4. <wbr><span style="word-wrap:normal; word-break:normal; color:rgb(255,0,0)">靜態(tài)變量</span>:</wbr>

    這個(gè)沒(méi)什么好說(shuō)的,就是類(lèi)變量,類(lèi)的所有實(shí)例都共享,我們只需知道,在方法區(qū)有個(gè)靜態(tài)區(qū),靜態(tài)區(qū)專(zhuān)門(mén)存放靜態(tài)變量和靜態(tài)塊。

  5. <wbr></wbr> 到類(lèi) classloader 的引用 到該類(lèi)的類(lèi)裝載器的引用。
  6. <wbr></wbr> 到類(lèi) class 的引用 虛擬機(jī)為每一個(gè)被裝載的類(lèi)型創(chuàng)建一個(gè) class 實(shí)例,用來(lái)代表這個(gè)被裝載的類(lèi)。 <wbr></wbr>

<wbr></wbr> <wbr></wbr> 由此我們可以知道反射的基礎(chǔ)

在裝載類(lèi)的時(shí)候,加入方法區(qū)中的所有信息,最后都會(huì)形成Class類(lèi)的實(shí)例,代表這個(gè)被裝載的類(lèi)。方法區(qū)中的所有的信息,都是可以通過(guò)這個(gè)Class類(lèi)對(duì)象反射得 到。 我們知道對(duì)象是類(lèi)的實(shí)例,類(lèi)是相同結(jié)構(gòu)的對(duì)象的一種抽象。同類(lèi)的各個(gè)對(duì)象之間,其實(shí)是擁有相同的結(jié)構(gòu)(屬性),擁有相同的功能(方法), 各個(gè)對(duì)象的區(qū)別只在于屬性值的不同
<wbr><wbr>同樣的,我們所有的類(lèi),其實(shí)都是Class類(lèi)的實(shí)例,他們都擁有相同的結(jié)構(gòu)-----Field數(shù)組、Method數(shù)組。而各個(gè)類(lèi)中的屬性都是Field屬性的一個(gè)具體屬性值,方法都是Method屬性的一個(gè)具體屬性值。</wbr></wbr>

<wbr></wbr>

<wbr><span style="word-wrap:normal; word-break:normal; line-height:24px; font-size:14px"><span style="word-wrap:normal; word-break:normal; color:rgb(0,204,255)"><span style="color:#000000; word-wrap:normal; word-break:normal"><strong>在運(yùn)行時(shí),JVM從常量池中獲得符號(hào)引用,然后在運(yùn)行時(shí)解析成引用項(xiàng)的實(shí)際地址,最后通過(guò)常量池中的全限定名、方法和字段描述符,把當(dāng)前類(lèi)或接口中的代碼與其它類(lèi)或接口中的代碼聯(lián)系起來(lái)。</strong></span></span></span></wbr>

<wbr></wbr>

1.2 Java棧

JVM 棧是程序運(yùn)行時(shí)單位,決定了程序如何執(zhí)行,或者說(shuō)數(shù)據(jù)如何處理。

Java 中,一個(gè)線程就會(huì)有一個(gè)線程的 JVM 棧與之對(duì)應(yīng),因?yàn)椴贿^(guò)的線程執(zhí)行邏輯顯然不同,因此都需要一個(gè)獨(dú)立的 JVM 棧來(lái)存放該線程的執(zhí)行邏輯。

對(duì)方法的調(diào)用:

Java 棧內(nèi)存,以 的形式存放 本地方法 調(diào)用狀態(tài) ,包括方法調(diào)用的 參數(shù) 局部變量、中間結(jié)果 等(方法都是以方法幀的形式存放在方法區(qū)的),每調(diào)用一個(gè)方法就將對(duì)應(yīng)該方法的方法幀壓入 Java 棧,成為當(dāng)前方法幀。當(dāng)調(diào)用結(jié)束 ( 返回 ) 時(shí),就彈出該幀。

<wbr></wbr>

這意味著:

在方法中定義的一些 基本類(lèi)型 的變量和 引用變量 都在方法的棧內(nèi)存中分配。 當(dāng)在一段代碼塊定義一個(gè)變量時(shí), Java 就在棧中為這個(gè)變量分配內(nèi)存空間,當(dāng)超過(guò)變量的作用域后(方法執(zhí)行完成后), Java 會(huì)自動(dòng)釋放掉為該變量所分配的內(nèi)存空間,該內(nèi)存空間可以立即被另作它用 -------- 同時(shí),因?yàn)樽兞勘会尫牛撟兞繉?duì)應(yīng)的對(duì)象,也就失去了引用,也就變成了可以被gc對(duì)象回收的垃圾。


因此我們可以知道成員變量與局部變量的區(qū)別:

<wbr></wbr>

局部變量,在方法內(nèi)部聲明,當(dāng)該方法運(yùn)行完時(shí),內(nèi)存即被釋放。
成員變量,只要該對(duì)象還在,哪怕某一個(gè)方法運(yùn)行完了,還是存在。
從系統(tǒng)的角度來(lái)說(shuō),聲明局部變量有利于內(nèi)存空間的更高效利用(方法運(yùn)行完即回收)。
成員變量可用于各個(gè)方法間進(jìn)行數(shù)據(jù)共享。

<wbr></wbr>

Java 棧內(nèi)存的組成:
局部變量區(qū)、操作數(shù)棧、幀數(shù)據(jù)區(qū)組成。
(1):局部變量區(qū)為一個(gè)以字為單位的數(shù)組,每個(gè)數(shù)組元素對(duì)應(yīng)一個(gè)局部變量的值。調(diào)用方法時(shí),將方法的局部變量組成一個(gè)數(shù)組,通過(guò)索引來(lái)訪問(wèn)。若為非靜態(tài)方法,則加入一個(gè)隱含的引用參數(shù)this,該參數(shù)指向調(diào)用這個(gè)方法的對(duì)象。而靜態(tài)方法則沒(méi)有this參數(shù)。因此,對(duì)象無(wú)法調(diào)用靜態(tài)方法。

<wbr></wbr>

由此,我們可以知道,方法什么時(shí)候設(shè)計(jì)為靜態(tài),什么時(shí)候?yàn)榉庆o態(tài)?

前面已經(jīng)說(shuō)過(guò),對(duì)象是類(lèi)的一個(gè)實(shí)例,各個(gè)對(duì)象結(jié)構(gòu)相同,只是屬性不同。
而靜態(tài)方法是對(duì)象無(wú)法調(diào)用的。
所以,靜態(tài)方法適合那些工具類(lèi)中的工具方法,這些類(lèi)只是用來(lái)實(shí)現(xiàn)一些功能,也不需要產(chǎn)生對(duì)象,通過(guò)設(shè)置對(duì)象的屬性來(lái)得到各個(gè)不同的個(gè)體。


(2):操作數(shù)棧也是一個(gè)數(shù)組,但是通過(guò)棧操作來(lái)訪問(wèn)。所謂操作數(shù)是那些被指令操作的數(shù)據(jù)。當(dāng)需要對(duì)參數(shù)操作時(shí)如a=b+c,就將即將被操作的參數(shù)壓棧,如將b 和c 壓棧,然后由操作指令將它們彈出,并執(zhí)行操作。虛擬機(jī)將操作數(shù)棧作為工作區(qū)。
(3):幀數(shù)據(jù)區(qū)處理常量池解析,異常處理等

<wbr></wbr>

1.3 java堆<wbr></wbr>

<wbr><wbr><wbr>java的堆是一個(gè)運(yùn)行時(shí)的數(shù)據(jù)區(qū),用來(lái)存儲(chǔ)數(shù)據(jù)的單元,存放通過(guò)new關(guān)鍵字新建的</wbr></wbr></wbr> 對(duì)象 數(shù)組 ,對(duì)象從中分配內(nèi)存。
<wbr><wbr><wbr>在堆中聲明的對(duì)象,是不能直接訪問(wèn)的,必須通過(guò)在棧中聲明的指向該引用的變量來(lái)調(diào)用。引用變量就相當(dāng)于是為數(shù)組或?qū)ο笃鸬囊粋€(gè)名稱(chēng),以后就可以在程序中使用棧中的引用變量來(lái)訪問(wèn)堆中的數(shù)組或?qū)ο蟆?lt;/wbr></wbr></wbr>
<wbr><wbr></wbr></wbr>

<wbr><wbr></wbr></wbr> <wbr>由此我們可以知道,引用類(lèi)型變量和對(duì)象的區(qū)別:<wbr></wbr></wbr>

聲明的對(duì)象是在堆內(nèi)存中初始化的,真正用來(lái)存儲(chǔ)數(shù)據(jù)的。不能直接訪問(wèn)。

引用類(lèi)型變量是保存在棧當(dāng)中的,一個(gè)用來(lái)引用堆中對(duì)象的符號(hào)而已(指針)。


堆與棧的比較
JAVA堆與棧都是用來(lái)存放數(shù)據(jù)的,那么他們之間到底有什么差異呢?既然棧也能存放數(shù)據(jù),為什么還要設(shè)計(jì)堆呢?


1. 從存放數(shù)據(jù)的角度:

<wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr> 前面我們已經(jīng)說(shuō)明:

<wbr><wbr><wbr>棧中存放的是基本類(lèi)型的變量</wbr></wbr></wbr> or 引用類(lèi)型的變量

<wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr> 堆中存放的是對(duì)象 or 數(shù)組對(duì)象.

<wbr><wbr><wbr><wbr>在棧中,引用變量的大小為32位,基本類(lèi)型為1-8個(gè)字節(jié)。</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr>但是對(duì)象的大小和數(shù)組的大小是動(dòng)態(tài)的,這也決定了堆中數(shù)據(jù)的動(dòng)態(tài)性,因?yàn)樗窃谶\(yùn)行時(shí)動(dòng)態(tài)分配內(nèi)存的,</wbr></wbr></wbr></wbr> 生存期也不必在編譯時(shí)確定, Java 的垃圾收集器會(huì)自動(dòng)收走這些不再使用的數(shù)據(jù)。

<wbr></wbr>

2. 從數(shù)據(jù)共享的角度:

<wbr><wbr>1).在單個(gè)線程類(lèi),棧中的數(shù)據(jù)可共享</wbr></wbr>

<wbr><wbr>例如我們定義:</wbr></wbr>

Java代碼 復(fù)制代碼 <wbr><a title="收藏這段代碼" style="text-decoration:underline; color:rgb(106,99,82)"><img alt="收藏代碼" src="http://java-mzd.iteye.com/images/icon_star.png" title="Java中運(yùn)行時(shí)內(nèi)存結(jié)構(gòu)補(bǔ)充" style="margin:0px; padding:0px; border:0px; list-style:none"></a></wbr>
  1. int <wbr>a=</wbr> 3 ; <wbr><wbr></wbr></wbr>
  2. int <wbr>b=</wbr> 3 ;<wbr><wbr></wbr></wbr>

<wbr><wbr></wbr></wbr> 編譯器先處理int a = 3;首先它會(huì)在棧中創(chuàng)建一個(gè)變量為a 的引用,然后查找棧中是否有3 這個(gè)值,如果沒(méi)找到,就將3 存放進(jìn)來(lái),然后將a 指向3。接著處理int b = 3;在創(chuàng)建完b 的引用變量后,因?yàn)樵跅V幸呀?jīng)有3這個(gè)值,便將b 直接指向3。這樣,就出現(xiàn)了a 與b 同時(shí)均指向3的情況。

<wbr><wbr>而如果我們定義:</wbr></wbr> <wbr></wbr>

Java代碼 復(fù)制代碼 <wbr><a title="收藏這段代碼" style="text-decoration:underline; color:rgb(106,99,82)"><img alt="收藏代碼" src="http://java-mzd.iteye.com/images/icon_star.png" title="Java中運(yùn)行時(shí)內(nèi)存結(jié)構(gòu)補(bǔ)充" style="margin:0px; padding:0px; border:0px; list-style:none"></a></wbr>
  1. Integer<wbr>a=</wbr> new <wbr>Integer(</wbr> 3 ); //(1) <wbr><wbr></wbr></wbr>
  2. Integer<wbr>b=</wbr> new <wbr>Integer(</wbr> 3 ); //(2) <wbr><wbr></wbr></wbr>

<wbr><wbr></wbr></wbr> 這個(gè)時(shí)候執(zhí)行過(guò)程為:在執(zhí)行(1)時(shí),首先在棧中創(chuàng)建一個(gè)變量a,然后在堆內(nèi)存中實(shí)例化一個(gè)對(duì)象,并且將變量a指向這個(gè)實(shí)例化的對(duì)象。在執(zhí)行(2)時(shí),過(guò)程類(lèi)似,此時(shí),在堆內(nèi)存中,會(huì)有兩個(gè)Integer類(lèi)型的對(duì)象。<wbr></wbr>

<wbr></wbr>

<wbr><wbr>2).<span style="word-wrap:normal; word-break:normal; color:rgb(255,0,0)"><strong>在進(jìn)程的各個(gè)線程之間,數(shù)據(jù)的共享通過(guò)堆來(lái)實(shí)現(xiàn)</strong></span></wbr></wbr>

<wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr> 例:那么,在多線程開(kāi)發(fā)中,我們的數(shù)據(jù)共享又是怎么實(shí)現(xiàn)的呢?
Java中運(yùn)行時(shí)內(nèi)存結(jié)構(gòu)補(bǔ)充

如圖所示,堆中的數(shù)據(jù)是所有線程棧所共享的,我們可以通過(guò)參數(shù)傳遞,將一個(gè)堆中的數(shù)據(jù)傳入各個(gè)棧的工作內(nèi)存中,從而實(shí)現(xiàn)多個(gè)線程間的數(shù)據(jù)共享

(多個(gè)進(jìn)程間的數(shù)據(jù)共享則需要通過(guò)網(wǎng)絡(luò)傳輸了。)<wbr></wbr>

<wbr></wbr>

3.從程序設(shè)計(jì)的的角度:

從軟件設(shè)計(jì)的角度看,JVM棧代表了處理邏輯,而JVM堆代表了數(shù)據(jù)。這樣分開(kāi),使得處理邏輯更為清晰。分而治之的思想。這種隔離、模塊化的思想在軟件設(shè)計(jì)的方方面面都有體現(xiàn)。


4.值傳遞和引用傳遞的真相

有了以上關(guān)于棧和堆的種種了解后,我們很容易就可以知道值傳遞和引用傳遞的真相:

1.程序運(yùn)行永遠(yuǎn)都是在JVM棧中進(jìn)行的,因而參數(shù)傳遞時(shí),只存在傳遞基本類(lèi)型和對(duì)象引用的問(wèn)題。不會(huì)直接傳對(duì)象本身。

但是傳引用的錯(cuò)覺(jué)是如何造成的呢?

在運(yùn)行JVM棧中,基本類(lèi)型和引用的處理是一樣的,都是傳值,所以,如果是傳引用的方法調(diào)用,也同時(shí)可以理解為“傳引用值”的傳值調(diào)用,即引用的處理跟基本類(lèi)型是完全一樣的。

但是當(dāng)進(jìn)入被調(diào)用方法時(shí),被傳遞的這個(gè)引用的值,被程序解釋(或者查找)到JVM堆中的對(duì)象,這個(gè)時(shí)候才對(duì)應(yīng)到真正的對(duì)象。

如果此時(shí)進(jìn)行修改,修改的是引用對(duì)應(yīng)的對(duì)象,而不是引用本身,即:修改的是JVM堆中的數(shù)據(jù)。所以這個(gè)修改是可以保持的了。

從某種意義上來(lái)說(shuō) 對(duì)象都 是由基本類(lèi)型組成的。 <wbr></wbr>

可以把一個(gè)對(duì)象看作為一棵樹(shù),對(duì)象的屬性如果還是對(duì)象,則還是一顆樹(shù)(即非葉子節(jié)點(diǎn)),基本類(lèi)型則為樹(shù)的葉子節(jié)點(diǎn)。程序參數(shù)傳遞時(shí),被傳遞的值本身都是不能進(jìn)行修改的,但是,如果這個(gè)值是一個(gè)非葉子節(jié)點(diǎn)(即一個(gè)對(duì)象引用),則可以修改這個(gè)節(jié)點(diǎn)下面的所有內(nèi)容。<wbr></wbr>


其實(shí),面向?qū)ο蠓绞降某绦蚺c以前結(jié)構(gòu)化的程序在執(zhí)行上沒(méi)有任何區(qū)別

面向?qū)ο蟮囊耄皇? 改變了我們 對(duì)待問(wèn)題的思考方式,而更接近于自然方式的思考。

當(dāng)我們把對(duì)象拆開(kāi),其實(shí)對(duì)象的屬性就是數(shù)據(jù),存放在JVM堆中;而對(duì)象的行為(方法),就是運(yùn)行邏輯,放在JVM棧中。我們?cè)诰帉?xiě)對(duì)象的時(shí)候,其實(shí)即編寫(xiě)了數(shù)據(jù)結(jié)構(gòu),也編寫(xiě)的處理數(shù)據(jù)的邏輯。

原文地址 :http://blog.sina.com.cn/s/blog_67fdef9001011nzl.html

Java中運(yùn)行時(shí)內(nèi)存結(jié)構(gòu)補(bǔ)充


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 五月花在线观看播放视频 | 亚洲黄色小视频 | 色综合一区 | 欧美亚洲精品一区二三 | 奇米在线观看 | 18禁片一级毛片视频播放免费看 | 2021最新国产成人精品免费 | 国产97公开成人免费视频 | 午夜 福利 | 欧美成人免费一级人片 | 五月婷婷之综合激情 | 九七97影院理论片手机在线观看 | 青青草国产一区二区三区 | 在线免费观看一级毛片 | 欧美一区中文字幕 | 九九九九九九精品免费 | 亚洲欧美在线综合一区二区三区 | 麻豆精品久久久一区二区 | 全免费午夜一级毛片真人 | 久久久噜噜噜久久网 | 日本一级aaaa特黄毛片 | 91系列| 国产一级免费在线观看 | 国产精品亚欧美一区二区三区 | 欧美成人啪啪看片 | 亚洲国产高清在线精品一区 | 国产一区二区三区精品久久呦 | 久久欧美精品 | 激情奇米| 欧美成人免费观看久久 | 99精品久久久久久久免费看蜜月 | 久久www免费人成高清 | 日韩欧美一区二区三区久久 | 中文字幕日韩一区二区三区不 | 久久亚洲精品一区二区三区浴池 | 亚洲国产成人久久一区久久 | 国产一二精品 | 亚洲视频污 | 狠狠狠狠狠狠狠狠狠狠 | 日韩精品一区二区在线观看 | 久久天天躁狠狠躁夜夜躁 |