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

Java內(nèi)存分配管理

系統(tǒng) 2181 0

http://java-mzd.iteye.com/blog/848635

?

P.S.

想寫這篇總結(jié)醞釀了有個(gè)來(lái)月了,卻始終感覺(jué)還差點(diǎn)什么東西,一直未敢動(dòng)筆。

? ? ? ? 最近兩天連夜奮戰(zhàn), 重新整理下 前面查閱的資料、筆記,還是決定將它寫出來(lái)。

? ? ? ? 現(xiàn)在提出幾個(gè)問(wèn)題, 如果都能熟練回答的大蝦,請(qǐng)您飄過(guò). 如以往一樣,我是小菜,本文自然也是針對(duì)小菜階層的總結(jié)。

?

首先是概念層面的幾個(gè)問(wèn)題:

?

  • Java中運(yùn)行時(shí)內(nèi)存結(jié)構(gòu)有哪幾種?
  • Java中為什么要設(shè)計(jì)堆棧分離?
  • Java多線程中是如何實(shí)現(xiàn)數(shù)據(jù)共享的?
  • Java反射的基礎(chǔ)是什么?

?

?

?

然后是運(yùn)用層面:

  • 引用類型變量和對(duì)象的區(qū)別?
  • 什么情況下用局部變量,什么情況下用成員變量?
  • 數(shù)組如何初始化?聲明一個(gè)數(shù)組的過(guò)程中,如何分配內(nèi)存?
  • 聲明基本類型數(shù)組和聲明引用類型的數(shù)組,初始化時(shí),內(nèi)存分配機(jī)制有什么區(qū)?
  • 在什么情況下,我們的方法設(shè)計(jì)為靜態(tài)化,為什么?(上次胡老師問(wèn)文奇,問(wèn)的啞口無(wú)言,當(dāng)時(shí)想回答,卻老感覺(jué)表述不清楚,這里也簡(jiǎn)單說(shuō)明一下)

?

?

?

?

?

?

?

好了,問(wèn)題提完了, 如果您都能一眼看出答案,那么,沒(méi)有必要再浪費(fèi)您寶貴的時(shí)間看下去了

如果您還不太明白,請(qǐng)跟隨我一路走下去。

?

?

?

?

?

?

?

?

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

? ? 1.1 方法區(qū): ?

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

? ??

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

? ? ? ? ? ? 1.1.1 類的基本信息:

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

?

?

?

?

?

?

?

? ? ? ? ? ? ?1.1.2 已裝載類的詳細(xì)信息

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

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

  2. ? 字段信息

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

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

  3. ? 方法信息

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

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

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

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

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

? ? 由此我們可以知道反射的基礎(chǔ)

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


?

? 在運(yùn)行時(shí),JVM從常量池中獲得符號(hào)引用,然后在運(yùn)行時(shí)解析成引用項(xiàng)的實(shí)際地址,最后通過(guò)常量池中的全限定名、方法和字段描述符,把當(dāng)前類或接口中的代碼與其它類或接口中的代碼聯(lián)系起來(lái)。

?

?

?

?

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í),就彈出該幀。

?

這意味著:

在方法中定義的一些 基本類型 的變量和 引用變量 都在方法的棧內(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ū)別:

局部變量,在方法內(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ù)共享。

?

?

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)方法。

?

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

前面已經(jīng)說(shuō)過(guò),對(duì)象是類的一個(gè)實(shí)例,各個(gè)對(duì)象結(jié)構(gòu)相同,只是屬性不同。
而靜態(tài)方法是對(duì)象無(wú)法調(diào)用的。
所以,靜態(tà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ū)處理常量池解析,異常處理等

?

1.3 java堆?

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

? ? ?由此我們可以知道,引用類型變量和對(duì)象的區(qū)別:?

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

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


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


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

? ? ?? 前面我們已經(jīng)說(shuō)明:

? ? ? 棧中存放的是基本類型的變量 or 引用類型的變量

? ? ? ? 堆中存放的是對(duì)象 or 數(shù)組對(duì)象.

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

?

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

? ? 1).在單個(gè)線程類,棧中的數(shù)據(jù)可共享

? ? 例如我們定義:

Java代碼 復(fù)制代碼
  1. int ?a= 3 ; ??
  2. int ?b= 3 ;??
       int a=3;
 int b=3;
    

?

? ? 編譯器先處理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的情況。

? ? 而如果我們定義: ?

Java代碼 復(fù)制代碼
  1. Integer?a= new ?Integer( 3 ); //(1) ??
  2. Integer?b= new ?Integer( 3 ); //(2) ??
      Integer a=new Integer(3);//(1)
Integer b=new Integer(3);//(2)
    

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

?

? ? 2). 在進(jìn)程的各個(gè)線程之間,數(shù)據(jù)的共享通過(guò)堆來(lái)實(shí)現(xiàn)

? ? ? ? 例:那么,在多線程開(kāi)發(fā)中,我們的數(shù)據(jù)共享又是怎么實(shí)現(xiàn)的呢?
Java內(nèi)存分配管理

?

? 如圖所示,堆中的數(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ò)傳輸了。)?

?

?

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í),只存在傳遞基本類型和對(duì)象引用的問(wèn)題。不會(huì)直接傳對(duì)象本身。

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

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

但是當(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ì)象都 是由基本類型組成的。 ?

?

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

?

?

?


其實(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è)诰帉憣?duì)象的時(shí)候,其實(shí)即編寫了數(shù)據(jù)結(jié)構(gòu),也編寫的處理數(shù)據(jù)的邏輯。?

?

?

P.S

?

關(guān)于數(shù)組的內(nèi)存分配,對(duì)象初始化的內(nèi)存分配等問(wèn)題,由于篇幅問(wèn)題,下次再搞個(gè)專題寫吧。

?連續(xù)幾天幾夜對(duì)著此文了。想吐的很,先到這里吧。

  • Java內(nèi)存分配管理
  • 大小: 13.2 KB

Java內(nèi)存分配管理


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

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

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

您的支持是博主寫作最大的動(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ì)您有幫助就好】

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

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 中文一区二区视频 | 91啦视频在线观看 | 久9视频这里只有精品8 | 5060一级毛片 | 一级一毛片a级毛片 | 精品国产精品 | 亚洲另类在线视频 | 偷偷鲁国内视频视频在线 | 天天爱天天做久久天天狠狼 | 国产亚洲精品激情一区二区三区 | www日韩中文字幕在线看 | 国产高清一区二区三区视频 | 一本色道久久88加勒比—综合 | 久久久噜久噜久久gif动图 | 欧美午夜视频一区二区三区 | 999伊人 | 99精品国产福利在线观看 | 久久久综合色 | 亚洲专区欧美 | 国内精品自在自线视频香蕉 | 9999在线观看 | 八戒久久精品一区二区三区 | 一区二区不卡 | 五月婷婷色网 | a视频在线播放 | 看全色黄大色黄大片 视 | 亚洲精品不卡久久久久久 | 欧美日本综合一区二区三区 | 4htv影院永久免费在线地址 | 欧美70一80老妇性大片 | 久久福利资源网站免费看 | www.黄网站| 四虎影视免费 | 天堂网一区二区 | 久久久久国产精品免费免费不卡 | 日韩欧美国产中文 | 高清性色生活片久久久 | 色综合久久综合网欧美综合网 | 综合免费一区二区三区 | 国产欧美精品区一区二区三区 | 国产亚洲精品日韩综合网 |