java虛擬機

          JVM specification對JVM內存的描述

          首先我們來了解JVM specification中的JVM整體架構。如下圖:

           


              
          主要包括兩個子系統和兩個組件: Class loader(類裝載器) 子系統,Execution engine(執行引擎) 子系統;Runtime data area (運行時數據區域)組件, Native interface(本地接口)組件。
               Class loader
          子系統的作用 :根據給定的全限定名類名( java.lang.Object)來裝載class文件的內容到 Runtime data area中的method area(方法區域)Javsa程序員可以extends java.lang.ClassLoader類來寫自己的Class loader
                Execution engine
          子系統的作用 :執行classes中的指令。任何JVM specification實現(JDK)的核心是Execution engine 換句話說:Sun JDK IBMJDK好壞主要取決于他們各自實現的Execution  engine的好壞。每個運行中的線程都有一個Execution engine的實例。
               Native interface
          組件 :與native libraries交互,是其它編程語言交互的接口。 
               Runtime data area
          組件:這個組件就是JVM中的內存

          • 運行時數據組件的詳解介紹:
              

          Runtime data area 主要包括五個部分:Heap (堆), Method Area(方法區域), Java Stack(java的棧), Program Counter(程序計數器), Native method stack(本地方法棧)。Heap 和Method Area是被所有線程的共享使用的;而Java stack, Program counter 和Native method stack是以線程為粒度的,每個線程獨自擁有。

          Heap
          Java程序在運行時創建的所有類實或數組都放在同一個堆中。
          而一個Java虛擬實例中只存在一個堆空間,因此所有線程都將共享這個堆。每一個java程序獨占一個JVM實例,因而每個java程序都有它自己的堆空間,它們不會彼此干擾。但是同一java程序的多個線程都共享著同一個堆空間,就得考慮多線程訪問對象(堆數據)的同步問題。 (這里可能出現的異常java.lang.OutOfMemoryError: Java heap space)

          JVM堆一般又可以分為以下三部分:

          Ø Perm

          Perm代主要保存class,method,filed對象,這部門的空間一般不會溢出,除非一次性加載了很多的類,不過在涉及到熱部署的應用服務器的時候,有時候會遇到java.lang.OutOfMemoryError : PermGen space 的錯誤,造成這個錯誤的很大原因就有可能是每次都重新部署,但是重新部署后,類的class沒有被卸載掉,這樣就造成了大量的class對象保存在了perm中,這種情況下,一般重新啟動應用服務器可以解決問題。

          Ø Tenured

          Tenured區主要保存生命周期長的對象,一般是一些老的對象,當一些對象在Young復制轉移一定的次數以后,對象就會被轉移到Tenured區,一般如果系統中用了application級別的緩存,緩存中的對象往往會被轉移到這一區間。

          Ø Young

          Young區被劃分為三部分,Eden區和兩個大小嚴格相同的Survivor區,其中Survivor區間中,某一時刻只有其中一個是被使用的,另外一個留做垃圾收集時復制對象用,在Young區間變滿的時候,minor GC就會將存活的對象移到空閑的Survivor區間中,根據JVM的策略,在經過幾次垃圾收集后,任然存活于Survivor的對象將被移動到Tenured區間。


          Method area
          在Java虛擬機中,被裝載的class的信息存儲在Method area的內存中。
          當虛擬機裝載某個類型時,它使用類裝載器定位相應的class文件,然后讀入這個class文件內容并把它傳輸到虛擬機中。緊接著虛擬機提取其中的類型信息,并將這些信息存儲到方法區。該類型中的類(靜態)變量同樣也存儲在方法區中。與Heap 一樣,method area是多線程共享的,因此要考慮多線程訪問的同步問題。比如,假設同時兩個線程都企圖訪問一個名為Lava的類,而這個類還沒有內裝載入虛擬機,那么,這時應該只有一個線程去裝載它,而另一個線程則只能等待。 (這里可能出現的異常java.lang.OutOfMemoryError: PermGen full)

          Java stack
                 Java stack以幀為單位保存線程的運行狀態。虛擬機只會直接對Java stack執行兩種操作:以幀為單位的壓棧或出棧。
          每當線程調用一個方法的時候,就對當前狀態作為一個幀保存到java stack中(壓棧);當一個方法調用返回時,從java stack彈出一個幀(出棧)。棧的大小是有一定的限制,這個可能出現StackOverFlow問題。 下面的程序可以說明這個問題。

           

          public class TestStackOverFlow {
           
               public static void main(String[] args) {
           
                      Recursive r = new Recursive();
                      r.doit(10000);
                      // Exception in thread "main" java.lang.StackOverflowError
               }
           
          }
           
          class Recursive {
           
               public int doit(int t) {
                      if (t <= 1) {
                              return 1;
                      }
                      return t + doit(t - 1);
               }
           
          }

           

          Program counter
          每個運行中的Java程序,每一個線程都有它自己的PC寄存器,也是該線程啟動時創建的。PC寄存器的內容總是指向下一條將被執行指令的餓&ldquo;地址&rdquo;,這里的&ldquo;地址&rdquo;可以是一個本地指針,也可以是在方法區中相對應于該方法起始指令的偏移量。

          Native method stack
          對于一個運行中的Java程序而言,它還能會用到一些跟本地方法相關的數據區。當某個線程調用一個本地方法時,它就進入了一個全新的并且不再受虛擬機限制的世界。本地方法可以通過本地方法接口來訪問虛擬機的運行時數據區,不止與此,它還可以做任何它想做的事情。比如,可以調用寄存器,或在操作系統中分配內存等。總之,本地方法具有和JVM相同的能力和權限。 (這里出現JVM無法控制的內存溢出問題native heap OutOfMemory )

          JVM提供了相應的參數來對內存大小進行配置。



          正如上面描述,JVM中堆被分為了3個大的區間,同時JVM也提供了一些選項對Young,Tenured的大小進行控制。

          Ø Total Heap 

          -Xms :指定了JVM初始啟動以后初始化內存

          -Xmx:指定JVM堆得最大內存,在JVM啟動以后,會分配-Xmx參數指定大小的內存給JVM,但是不一定全部使用,JVM會根據-Xms參數來調節真正用于JVM的內存

          -Xmx -Xms之差就是三個Virtual空間的大小

          Ø Young Generation

          -XX:NewRatio=8意味著tenured  young的比值81,這樣eden+2*survivor=1/9

          堆內存

          -XX:SurvivorRatio=32意味著eden和一個survivor的比值是321,這樣一個Survivor就占Young區的1/34.

          -Xmn 參數設置了年輕代的大小

          Ø Perm Generation

          -XX:PermSize=16M -XX:MaxPermSize=64M

          Thread Stack

          -XX:Xss=128K

           


          posted on 2012-02-27 15:35 陳睿 閱讀(528) 評論(1)  編輯  收藏 所屬分類: 高級

          評論

          # 一點不同的看法, 請教下[未登錄] 2012-10-11 15:59 帶著愛遠行

          博主好, 文章很好。但我對于運行時組件的那幅圖native處的調用有點不明白, 在jvm規范中并沒有說明會去調用操作系統的內存, 不知哪里有依據可以得出這個結論。
          原話是:native method stacks are typically allocated per thread when each thread is created.
          另外有點不明白的是,既然是調用操作系統的內存,那么為每個線程分配native method stacks又有什么意義呢,這塊內存用來保存什么?
          最后請教下運行時組件的那幅圖是不是博主自己畫的,問題比較多,哈哈。  回復  更多評論   

          導航

          <2012年2月>
          2930311234
          567891011
          12131415161718
          19202122232425
          26272829123
          45678910

          統計

          常用鏈接

          留言簿

          隨筆分類

          隨筆檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 平潭县| 文水县| 博野县| 巫溪县| 海伦市| 合作市| 绥化市| 青田县| 卢氏县| 吴堡县| 红桥区| 玉环县| 云霄县| 通河县| 清徐县| 佛坪县| 青川县| 尤溪县| 香港| 洛南县| 湘阴县| 扬州市| 伊宁市| 太湖县| 迁西县| 潮安县| 天津市| 广宁县| 饶河县| 公安县| 托克逊县| 旬阳县| 高雄县| 荆门市| 江永县| 年辖:市辖区| 朔州市| 朝阳县| 灯塔市| 西青区| 澄城县|