天天看點

JVM記憶體管理,虛拟機堆棧的了解

前言:C或者C++的記憶體申請和銷毀需要程式員自己控制,很容易記憶體洩漏和記憶體溢出且出現問題查找困難。Java在記憶體管理的優勢在于jvm自己申請和銷毀記憶體,不需要程式員關注記憶體問題,更專注于業務邏輯。那為什麼我們還需要了解JVM的記憶體管理機制和原理呢?第一、作為有追求的程式猿應該追根刨底,做到知自知彼;第二、當記憶體管理成為系統性能瓶頸時或者出現記憶體洩漏、記憶體溢出問題,程式猿隻有了解JVM的記憶體原理才能夠去優化和查找記憶體問題。

先上圖,給各位同學有個JVM記憶體整體的概念,下面會介紹虛拟機的記憶體各個區域,這個是了解JVM的第一步。

JVM記憶體管理,虛拟機堆棧的了解

程式計數器

程式計數器是位元組碼解釋器執行位元組碼的行号訓示,存放目前正在執行的位元組碼的位址。java多線程是通過線程輪流切換來擷取處理器的執行時間,任何一個時刻,一個處理器隻能處理一個線程的位元組碼,為了在切換線程後能恢複到正确的代碼位置, 是以每個線程都有自己獨立的程式計數器。此記憶體區域是jvm中唯一沒有OutOfMemeryError的區域。

虛拟機棧

經常說的堆和棧隻是泛指程式猿比較關注的是這兩塊記憶體區域,實際記憶體區域不止堆和棧。 虛拟機棧也是線程私有的,它的生命周期和線程一樣。虛拟機棧是java方法執行的記憶體模型,主要記錄局部變量表、操作數棧、動态連結、方法出口資訊等,每次方法的執行都伴随着棧幀的入棧和出棧。 局部變量表主要存放byte、short、int、char、boolean、long、float、double 這8種基本類型、對象引用。 虛拟機棧區域會報StackOverflowError和OutMemoryError錯誤,當請求的棧深度超過虛拟機棧的最大深度,會報StackOverflowError;若虛拟機棧自動擴容,當擴容時沒有足夠的記憶體時會報OutMemoryError錯誤。

本地方法棧

虛拟機棧是為調用java方法服務,本地方法棧是為調用本地native方法服務。

堆(Heap)

堆是記憶體中最大的一塊區域,用來存放數組、對象執行個體,是java 垃圾回收的主要對象,也稱為gc堆,也是程式猿最關注的記憶體區域。可以通過-Xms(最小堆記憶體)、-Xmx(最大堆記憶體)來設定堆的大小。 為了提高堆記憶體的使用率和垃圾回收的效率,堆記憶體分年輕代和老年代,年輕代為Eden、From Survivor、To Survivor,一般三個代的大小比例為8:1:1,為什麼要設定兩個Survivor代呢?因為新建立的對象都會進入Eden代,大部分Eden代的對象都是朝生夕死的,在年輕代通過複制算法回收垃圾時,可以利用From Survivor和To Survivor來回倒騰存活的對象,提高記憶體使用率和垃圾回收效率。 堆記憶體是公用的,線程共享的,同時堆記憶體會報OutofMemoryError。

方法區

方法區也是公用的,線程共享的。方法區存放類的資訊、類字段、類方法、常量、靜态變量以及及時編譯後的代碼等資料。在HotSpot虛拟機中,方法區被稱為永久代。

運作時常量池

運作時常量池是方法區中的一部分,主要存放在編譯期生成的字面量和符号引用,比如常量;在程式運作時也可以将常量放入常量池中,比如String類的intern()方法。

注:以上是自己的個人了解,如有錯誤請指正!