java虛擬機中的堆(heap)、棧(stack)、方法區(method area)

一、堆區java

  • 存儲的所有是對象,每一個對象都包含一個與之對應的class的信息。(class的目的是獲得操做指令)
  •  jvm只有一個heap區,被全部線程共享,不存放基本類型和對象引用,只存放對象自己

 堆的優劣勢:數組

  • 堆的優點是能夠動態的分配內存大小,生存期也沒必要事先告訴編譯器,java的垃圾收集器會自動收取這些再也不使用的數據

缺點是:數據結構

  • 因爲要在運行時動態分配內存,存取速度慢

二、棧區jvm

  • 每個線程包含一個stack區,只保存基本數據類型的對象和自定義對象的引用(不是對象),對象都存放在共享heap中
  • 每一個棧中的數據(基本數據類型和對象引用)都是私有的,其餘棧不能訪問

棧分爲3部分:線程

  • 基本類型變量區
  • 執行環境上下文
  • 操做指令區(存放操做指令)

棧的優點劣勢:3d

  • 存取速度比堆要快,僅次於直接位於CPU的寄存器
  • 但必須肯定的是存在stack中的數據大小與生存期必須是肯定的,缺少靈活性
  • 單個stack的數據能夠共享
  •  stack:是一個先進後出的數據結構,一般保存方法中的參數,局部變量
  • 在java中,全部基本類型和引用類型都在stack中儲存,棧中數據的生存空間通常在當前scopes內

三、方法區指針

  • 又叫靜態區,跟堆同樣,被全部的線程共享。方法區包含全部的class和static變量
  • 方法區中包含的都是在程序中永遠的惟一的元素

四、Java中不一樣的存儲數據的地方:對象

 寄存器(register)blog

  • 最快的存儲區,由於它位於不一樣於其餘存儲區的地方——處理器內部繼承

  • 可是寄存器的數量極其有限,因此寄存器由編譯器根據需求進行分配

  • 你不能直接控制,也不能在程序中感受到寄存器存在的任何跡象

堆棧(stack)

  • 位於通用RAM中,但經過它的「堆棧指針」能夠從處理器哪裏得到支持
  • 堆棧指針若向下移動,則分配新的內存;若向上移動,則釋放那些 內存
  • 一種快速有效的分配存儲方法,僅次於寄存器

堆(heap)

  • 通用性的內存池(也存在於RAM中),用於存放因此的JAVA對象
  • 好處是:編譯器不須要知道要從堆裏分配多少存儲區域,也沒必要知道存儲的數據在堆裏存活多長時間

  • 所以,在堆裏分配存儲有很大的靈活性

五、JVM內存模型

大多數JVM將內存分配爲:

  • Method Area(方法區)
  • Heap(堆)
  • Program Counter Register(程序計數器)
  • JAVA Method Stack(JAVA方法棧)
  • Native Method Stack(本地方法棧)

六、Method Area(方法區)

  • 線程共享,存儲已經被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等等
  • HotSpot虛擬機上開發部署人員更願意成爲「永久代」,Permanent Generation

類型信息

  • 類型的全限定名
  • 超類的全限定名
  • 直接超接口的全限定名
  • 類型標誌(該類是類類型仍是接口類型)
  • 類的訪問描述符(public、private、default、abstract、final、static)

類型的常量池

  • 存放該類型所用到的常量的有序集合
  • 包括直接常量(如字符串、整數、浮點數的常量)和對其餘類型、字段、方法的符號引用
  • 常量池中每個保存的常量都有一個索引,就像數組中的字段同樣
  • 常量池中保存中全部類型使用到的類型、字段、方法的字符引用,因此它也是動態鏈接的主要對象(在動態連接中起到核心做用)

字段信息(該類聲明的全部字段)

  • 字段修飾符(public、protect、private、default)
  • 字段的類型
  • 字段名稱

方法信息(包含類的全部方法,每一個方法包含如下信息)

  • 方法修飾符
  • 方法返回類型
  • 方法名
  • 方法參數個數、類型、順序等
  • 方法字節碼
  • 操做數棧和該方法在棧幀中的局部變量區大小
  • 異常表

類變量(靜態變量)

  • 該類全部對象共享的變量,即便沒有任何實例對象時,也能夠訪問的類變量。它們與類進行綁定

指向類加載器的引用

  • 每個被JVM加載的類型,都保存這個類加載器的引用,類加載器動態連接時會用到

指向Class實例的引用

  •  類加載的過程當中,虛擬機會建立該類型的Class實例,方法區中必須保存對該對象的引用
  • 經過Class.forName(String className)來查找得到該實例的引用,而後建立該類的對象

方法表

  • 爲了提升訪問效率,JVM可能會對每一個裝載的非抽象類,都建立一個數組
  • 數組的每一個元素是實例可能調用的方法的直接引用,包括父類中繼承過來的方法
  • 這個表在抽象類或者接口中是沒有的

運行時常量池(Runtime Constant Pool)

  •  Class文件中除了有類的版本、字段、方法、接口等描述信息外
  • 還有一項信息是常量池,用於存放編譯器生成的各類字面常量和符號引用
  • 這部份內容被類加載後進入方法區的運行時常量池中存放

運行時常量池相對於Class文件常量池的另一個特徵具備動態性

  • 能夠在運行期間將新的常量放入池中(典型的如String類的intern()方法)
  • 運行時常量池是把Class文件常量池加載進來,每一個類有一個獨立的
  • 剛開始時運行的時候常量池裏的連接都是符號連接(只用名字沒有實體),跟在Class文件裏的同樣
  • 邊運行邊把常量轉換成直接連接
相關文章
相關標籤/搜索