1.1方法區:方法區是系統分配的一個內存邏輯區域,是JVM在裝載類文件時,用于存儲類型信息的(類的描述信息)。方法區存放的信息包括:1.1.1類的基本信息:每個類的全限定名每個類的直接超類的全限定名(可約束類型轉換)" />

欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

Java中運行時內存結構補充

系統 2842 0

Java中運行時內存結構

<wbr><wbr></wbr></wbr> 1.1 方法區: <wbr></wbr>

方法區是系統分配的一個內存邏輯區域,是 JVM 在裝載類文件時,用于存儲類型信息的 ( 類的描述信息 )。

<wbr></wbr>

方法區存放的信息包括:

<wbr><wbr><wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr></wbr></wbr> 1.1.1 類的基本信息:

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

<wbr><wbr><wbr><wbr><wbr><wbr><wbr>1.1.2<strong>已裝載類的詳細信息</strong>:</wbr></wbr></wbr></wbr></wbr></wbr></wbr>

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

    在方法區中,每個類型都對應一個常量池,存放該類型所用到的所有常量,常量池中存儲了諸如 文字字符串、 final 變量值、類名和方法名常量。 它們以數組形式通過索引被訪問,是外部調用與類聯系及類型對象化的橋梁。(存的可能是個普通的字符串,然后經過常量池解析,則變成指向某個類的引用)

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

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

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

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

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

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

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

    這個沒什么好說的,就是類變量,類的所有實例都共享,我們只需知道,在方法區有個靜態區,靜態區專門存放靜態變量和靜態塊。

  5. <wbr></wbr> 到類 classloader 的引用 到該類的類裝載器的引用。
  6. <wbr></wbr> 到類 class 的引用 虛擬機為每一個被裝載的類型創建一個 class 實例,用來代表這個被裝載的類。 <wbr></wbr>

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

在裝載類的時候,加入方法區中的所有信息,最后都會形成Class類的實例,代表這個被裝載的類。方法區中的所有的信息,都是可以通過這個Class類對象反射得 到。 我們知道對象是類的實例,類是相同結構的對象的一種抽象。同類的各個對象之間,其實是擁有相同的結構(屬性),擁有相同的功能(方法), 各個對象的區別只在于屬性值的不同
<wbr><wbr>同樣的,我們所有的類,其實都是Class類的實例,他們都擁有相同的結構-----Field數組、Method數組。而各個類中的屬性都是Field屬性的一個具體屬性值,方法都是Method屬性的一個具體屬性值。</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>在運行時,JVM從常量池中獲得符號引用,然后在運行時解析成引用項的實際地址,最后通過常量池中的全限定名、方法和字段描述符,把當前類或接口中的代碼與其它類或接口中的代碼聯系起來。</strong></span></span></span></wbr>

<wbr></wbr>

1.2 Java棧

JVM 棧是程序運行時單位,決定了程序如何執行,或者說數據如何處理。

Java 中,一個線程就會有一個線程的 JVM 棧與之對應,因為不過的線程執行邏輯顯然不同,因此都需要一個獨立的 JVM 棧來存放該線程的執行邏輯。

對方法的調用:

Java 棧內存,以 的形式存放 本地方法 調用狀態 ,包括方法調用的 參數 局部變量、中間結果 等(方法都是以方法幀的形式存放在方法區的),每調用一個方法就將對應該方法的方法幀壓入 Java 棧,成為當前方法幀。當調用結束 ( 返回 ) 時,就彈出該幀。

<wbr></wbr>

這意味著:

在方法中定義的一些 基本類型 的變量和 引用變量 都在方法的棧內存中分配。 當在一段代碼塊定義一個變量時, Java 就在棧中為這個變量分配內存空間,當超過變量的作用域后(方法執行完成后), Java 會自動釋放掉為該變量所分配的內存空間,該內存空間可以立即被另作它用 -------- 同時,因為變量被釋放,該變量對應的對象,也就失去了引用,也就變成了可以被gc對象回收的垃圾。


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

<wbr></wbr>

局部變量,在方法內部聲明,當該方法運行完時,內存即被釋放。
成員變量,只要該對象還在,哪怕某一個方法運行完了,還是存在。
從系統的角度來說,聲明局部變量有利于內存空間的更高效利用(方法運行完即回收)。
成員變量可用于各個方法間進行數據共享。

<wbr></wbr>

Java 棧內存的組成:
局部變量區、操作數棧、幀數據區組成。
(1):局部變量區為一個以字為單位的數組,每個數組元素對應一個局部變量的值。調用方法時,將方法的局部變量組成一個數組,通過索引來訪問。若為非靜態方法,則加入一個隱含的引用參數this,該參數指向調用這個方法的對象。而靜態方法則沒有this參數。因此,對象無法調用靜態方法。

<wbr></wbr>

由此,我們可以知道,方法什么時候設計為靜態,什么時候為非靜態?

前面已經說過,對象是類的一個實例,各個對象結構相同,只是屬性不同。
而靜態方法是對象無法調用的。
所以,靜態方法適合那些工具類中的工具方法,這些類只是用來實現一些功能,也不需要產生對象,通過設置對象的屬性來得到各個不同的個體。


(2):操作數棧也是一個數組,但是通過棧操作來訪問。所謂操作數是那些被指令操作的數據。當需要對參數操作時如a=b+c,就將即將被操作的參數壓棧,如將b 和c 壓棧,然后由操作指令將它們彈出,并執行操作。虛擬機將操作數棧作為工作區。
(3):幀數據區處理常量池解析,異常處理等

<wbr></wbr>

1.3 java堆<wbr></wbr>

<wbr><wbr><wbr>java的堆是一個運行時的數據區,用來存儲數據的單元,存放通過new關鍵字新建的</wbr></wbr></wbr> 對象 數組 ,對象從中分配內存。
<wbr><wbr><wbr>在堆中聲明的對象,是不能直接訪問的,必須通過在棧中聲明的指向該引用的變量來調用。引用變量就相當于是為數組或對象起的一個名稱,以后就可以在程序中使用棧中的引用變量來訪問堆中的數組或對象。</wbr></wbr></wbr>
<wbr><wbr></wbr></wbr>

<wbr><wbr></wbr></wbr> <wbr>由此我們可以知道,引用類型變量和對象的區別:<wbr></wbr></wbr>

聲明的對象是在堆內存中初始化的,真正用來存儲數據的。不能直接訪問。

引用類型變量是保存在棧當中的,一個用來引用堆中對象的符號而已(指針)。


堆與棧的比較
JAVA堆與棧都是用來存放數據的,那么他們之間到底有什么差異呢?既然棧也能存放數據,為什么還要設計堆呢?


1. 從存放數據的角度:

<wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr> 前面我們已經說明:

<wbr><wbr><wbr>棧中存放的是基本類型的變量</wbr></wbr></wbr> or 引用類型的變量

<wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr> 堆中存放的是對象 or 數組對象.

<wbr><wbr><wbr><wbr>在棧中,引用變量的大小為32位,基本類型為1-8個字節。</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr>但是對象的大小和數組的大小是動態的,這也決定了堆中數據的動態性,因為它是在運行時動態分配內存的,</wbr></wbr></wbr></wbr> 生存期也不必在編譯時確定, Java 的垃圾收集器會自動收走這些不再使用的數據。

<wbr></wbr>

2. 從數據共享的角度:

<wbr><wbr>1).在單個線程類,棧中的數據可共享</wbr></wbr>

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

Java代碼 復制代碼 <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中運行時內存結構補充" 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;首先它會在棧中創建一個變量為a 的引用,然后查找棧中是否有3 這個值,如果沒找到,就將3 存放進來,然后將a 指向3。接著處理int b = 3;在創建完b 的引用變量后,因為在棧中已經有3這個值,便將b 直接指向3。這樣,就出現了a 與b 同時均指向3的情況。

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

Java代碼 復制代碼 <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中運行時內存結構補充" 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> 這個時候執行過程為:在執行(1)時,首先在棧中創建一個變量a,然后在堆內存中實例化一個對象,并且將變量a指向這個實例化的對象。在執行(2)時,過程類似,此時,在堆內存中,會有兩個Integer類型的對象。<wbr></wbr>

<wbr></wbr>

<wbr><wbr>2).<span style="word-wrap:normal; word-break:normal; color:rgb(255,0,0)"><strong>在進程的各個線程之間,數據的共享通過堆來實現</strong></span></wbr></wbr>

<wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr> 例:那么,在多線程開發中,我們的數據共享又是怎么實現的呢?
Java中運行時內存結構補充

如圖所示,堆中的數據是所有線程棧所共享的,我們可以通過參數傳遞,將一個堆中的數據傳入各個棧的工作內存中,從而實現多個線程間的數據共享

(多個進程間的數據共享則需要通過網絡傳輸了。)<wbr></wbr>

<wbr></wbr>

3.從程序設計的的角度:

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


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

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

1.程序運行永遠都是在JVM棧中進行的,因而參數傳遞時,只存在傳遞基本類型和對象引用的問題。不會直接傳對象本身。

但是傳引用的錯覺是如何造成的呢?

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

但是當進入被調用方法時,被傳遞的這個引用的值,被程序解釋(或者查找)到JVM堆中的對象,這個時候才對應到真正的對象。

如果此時進行修改,修改的是引用對應的對象,而不是引用本身,即:修改的是JVM堆中的數據。所以這個修改是可以保持的了。

從某種意義上來說 對象都 是由基本類型組成的。 <wbr></wbr>

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


其實,面向對象方式的程序與以前結構化的程序在執行上沒有任何區別

面向對象的引入,只是 改變了我們 對待問題的思考方式,而更接近于自然方式的思考。

當我們把對象拆開,其實對象的屬性就是數據,存放在JVM堆中;而對象的行為(方法),就是運行邏輯,放在JVM棧中。我們在編寫對象的時候,其實即編寫了數據結構,也編寫的處理數據的邏輯。

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

Java中運行時內存結構補充


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

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

【本文對您有幫助就好】

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

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 91精品电影 | 色婷婷.com| 精品国产91乱码一区二区三区 | 啪啪免费视频网站 | 亚洲天堂视频在线观看免费 | 草草视频在线 | 国产中文字幕久久 | 一级毛片视频在线 | 成人午夜视频免费 | 成人免费电影视频 | 色宅男看片午夜大片免费看 | 欧美123| 日韩精品极品视频在线观看免费 | 蜜桃日韩| 久久狠狠| 麻豆av电影在线观看 | 国产麻豆| 久久久久久国产视频 | 欧美又黄又嫩大片a级 | 国产乱在线观看视频 | 色资源网站 | 日韩卡1卡2 卡三卡2021老狼 | 91免费看片 | 久久精品国产99国产精品 | 欧美一级www | 成年人看的羞羞网站 | 天天操综合网 | 特黄特色的大片观看免费视频 | 色婷婷综合久久久中字幕精品久久 | 国产高清视频在线观看 | www.av在线免费观看 | 久草视频在线资源 | 久久亚洲国产精品日日av夜夜 | 美国一级片免费看 | 少妇的肉体的满足毛片 | 色搞搞| 激情五月色综合色婷婷 | 欧美日韩精品一区二区三区视频 | 新封神榜杨戬电影免费动画在线观看国语 | 亚洲 日本 欧美 日韩精品 | 亚洲蜜桃AV色情精品成人 |