1. 程式人生 > >JVM 堆與棧

JVM 堆與棧

這裡寫圖片描述

Java Heap Memory

      堆記憶體(heap memory)是被用來在runtime的時候給物件和jre的那些class分配記憶體的。注意是runtime的時候。不管你何時建立物件,建立任何一個物件,這些物件都是被建立在了heap空間裡的。那個我們熟悉的gc(垃圾回收站)負責把那些不再被引用(reference)的物件從heap memory中清理掉,這也是gc的職責所在。在heap空間裡建立的任何物件都是全域性訪問的。可以被應用程式的任何地方引用。

Java Stack Memory

      java裡的stack記憶體(stack memory)是被用來執行緒的執行的。也就是stack是執行緒級別的。而heap是物件級別的。這個stack裡邊包含了方法裡邊那些定義的值,這些值隨著一次方法執行完畢後就消失了;還包含了引用地址。這個引用地址就是對存放在heap memory中的一個連結。你可以理解為關係資料庫裡邊的外來鍵,nosql中的外鏈。總之你理解就行。stack memory由於她是個stack結構。所以呢,他也遵循LIFO,就是後進先出的順序。一個方法不論什麼時候被呼叫,一個針對該方法的全新的block就會在stack memory裡被建立,用來儲存這個方法裡的本地基本型別的值以及這個方法對其他物件的引用地址。一旦方法執行結束,這個block的狀態就變為unused了,就是變為了空閒狀態,就變為available了。宣佈單身了,等著下一個method來用她。stack memory的size相比heap memory的size要小得多。

      現在就讓我們上一個simple program來更好的理解一下堆疊memory。

public class Memory {
    public static void main(String[] args) { // Line1
        int i = 1; // Line 2
        Object obj = new Object(); // Line 3
        Memory mem = new Memory(); // Line 4
        mem.foo(obj); // Line 5
    } // Line 9

    private void
foo(Object param) { // Line 6 String str = param.toString(); //// Line 7 System.out.println(str); } // Line 8 }

      下面這個圖就展示了在上面這個程式中的stack和heap memory的儲存和引用關係。堆疊怎麼被用來儲存基本型別值(primitive value)以及物件以及物件的引用。
這裡寫圖片描述

接下來我們就一步步的來看上面的那個program的執行情況。

  • 一旦我們運行了這個程式,它就會把所有的runtime class load 到 heap空間。當main()方法在line1那個地方被發現後,Java Runtime就會建立stack memory給main()方法這個執行緒來用。

  • 在line2那個地方,我們建立了一個primitive(基本型別)的區域性變數,這個變數自然是被儲存到了main()的stack memory裡的。

  • 在line3那個位置,我們建立了一個物件,按照前面說的,這個物件自然是儲存在heap memory裡邊的,並且在stack memory裡邊也有個這個物件的引用地址被儲存了進去。line4的物件建立過程和line3是一樣的。

  • 現在我們來到了line5這個地方,這一行我們呼叫了foo()方法,這時候一個block在stack的頂部被建立,這個block現在專門為foo()方法服務。由於java是按值傳遞,所以在line6那個位置一個新的物件引用就會在foo() 方法的stack block中被建立。

  • 在line7那個位置,一個字串被建立,這個串是在heap空間的string池(String Pool)中。並且對這個string物件的引用自然也在foo()方法的stack空間裡被建立了。

  • 在line8那個地方foo()方法就被終止了,在方法結束的時候,在stack中為foo()分配的那個block重新變回空窗期,宣佈available了。

  • 在line9那個地方,main()方法也要結束了。自然為main()建立的stack memory就會被destory掉了。自此,Java Runtime 釋放所有的memory然後結束程式的執行!

heap memory與stack memory的區別

基於上面的那一堆解釋,我們現在可以很輕鬆的總結出以下不同之處:

1、heap用在一個application的很多地方,但stack memory只用於一個執行緒的執行。前者是物件級別,後者是執行緒級別。

2、只要是物件的建立,都是被儲存到heap space中,同時stack中有這個物件的引用地址。stack memory中只包含基本型別變數和儲存在heap space中的物件的引用變數。

3、 儲存在heap中的物件是全域性都可以訪問的,然而stack memory不能被其他執行緒訪問。

4、stack 的記憶體管理是使用LIFO的,然而heap的記憶體管理要更復雜,因為heap是被全域性使用的。因此heap memory被分為Young-Generation,Old-Generation等等,有關這個你可以去了解下java的gc(垃圾回收)機制。

5、 stack memory是短命的,然而heap memory則是application執行的整個生命週期都有他,直到application結束掉。

6、我們使用-Xms和-Xmx jam 引數來定義heap memory的啟動size和最大size。stack memory的size則是使用-Xss。

7、當stack memory滿了,那麼Java runtime就會丟擲一個java.lang.StackOverFlowError的異常。當heap memory 滿了,則會丟擲java.lang.OutOfMemoryError: Java Heap Space error.

8、stack memory相比heap memory來說是非常小的。另外由於記憶體分配比較簡單(LIFO),stack memory相比heap memory來說是非常快的。

其他

Stack :

  • local variables

Heap :

  • instance variables
  • static variables
  • objects

這裡寫圖片描述

這裡寫圖片描述

個人微信公眾號:
這裡寫圖片描述

相關推薦

JVM

Java Heap Memory       堆記憶體(heap memory)是被用來在runtime的時候給物件和jre的那些class分配記憶體的。注意是runtime的時候。不管你何時建立物件,建立任何一個物件,這些物件都是被建立在了heap空

JVM基礎:深入學習JVMJVM(轉)

面向 對象的引用 進入 信息 分離 字節 address 出現 運行 JVM棧解決程序的運行問題,即程序如何執行,或者說如何處理數據;JVM堆解決的是數據存儲的問題,即數據怎麽放、放在哪兒,另外JVM堆中存的是對象。JVM棧中存的是基本數據類型和JVM堆中對象的引用。 JV

JVM基礎:深入學習JVMJVM-的經典問題

JVM棧解決程式的執行問題,即程式如何執行,或者說如何處理資料; JVM堆解決的是資料儲存的問題,即資料怎麼放、放在哪兒,另外JVM堆中存的是物件。 JVM棧中存的是基本資料型別和JVM堆中物件的引用。 JVM基礎概念:JVM堆與JVM棧 資料型別 J

C#

完成 time bool 語言 收集器 一段 兩個 介紹 在一起 解釋1、棧是編譯期間就分配好的內存空間,因此你的代碼中必須就棧的大小有明確的定義;堆是程序運行期間動態分配的內存空間,你可以根據程序的運行情況確定要分配的堆內存的大小 解釋2、 存放在棧中時要管存儲順序,

Heap Spray:的協同攻擊

包含 src 而不是 blog shell hit 存在 完整 font 1:應用場景 在針對瀏覽器的攻擊中,常常會結合使用堆和棧協同利用漏洞。 (1)當瀏覽器或其使用的ActiveX 控件中存在溢出漏洞時,攻擊者就可以生成一個特殊的HTML 文件來觸發這個漏洞。 (2)不

讓你徹底明白JAVA中的區別

java程序 運行 一點 動態 自動變 key 空間 類型 lin 原文地址:http://www.2cto.com/kf/201302/190704.html 簡單的說: Java把內存劃分成兩種:一種是棧內存,一種是堆內存。 在函數中定義的一些基本類型的變量和對象的引用

程序的段、

.data 初始化 申請 font har lin -h tom 才會 1.程序就是編譯出來的鏡像,處於執行狀態的程序叫進程.一個程序可以執行多次,每次執行會產生一個進程. 2. 程序鏡像裏有分成很多個段: 段其實就是在程序鏡像文件裏從一個位置到另一個位置範圍裏存放某種

java中資料的5種儲存位置()

任何語言所編寫的程式,其中的各型別的資料都需要一個儲存位置,Java中資料的儲存位置分為以下5種: 1.暫存器 最快的儲存區,位於處理器內部,但是數量極其有限。所以暫存器根據需求進行自動分配,無法直接人為控制。 2.棧記憶體 位於RAM當中,通過堆疊指標可以從處理器獲得直接支援。堆疊指標向下

c/c++的 資料結構的的區別

一、預備知識—程式的記憶體分配 一個由c/C++編譯的程式佔用的記憶體分為以下幾個部分  1、棧區(stack)— 由編譯器自動分配釋放 ,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。  2、堆區(heap) — 一般由程式設計師分配釋放, 若程式設計

Jvm、方法區理解

堆解決的是資料儲存問題,即資料怎麼放,資料放哪。 棧解決程式的執行問題,即程式如何執行,或者說如何處理資料。 方法區則是輔助棧的一塊永久區(perm),解決堆疊資訊的產生,是先決條件。 堆 java

深入理解Javascript中的、淺拷貝深拷貝

Javascript中的淺拷貝與深拷貝 先從JavaScript的資料型別存放的位置堆疊開始說吧 什麼是堆疊? 我們知道計算機領域中堆疊是兩種資料結構,它們只能再一端(稱為棧頂(top))對資料項進行插入和刪除。 堆:佇列優先,先進先出,由作業系統自動分配釋放,存放函式的引數值,區域性變數的

java程式設計中的,你瞭解多少?

在JVM中記憶體有這5類 堆(Heap)存放關鍵字new建立的物件和陣列;java堆是jvm記憶體管理中最大的一塊,執行緒共享;當使用new建立物件時,不必指定分配空間的大小,jvm會動態自動分配一塊區域;在程式執行過程中,沒有指向此物件的引用時,此物件就被標記為可被回

C/C++:以及new簡單使用

C++中,記憶體分為5個區:堆、棧、自由儲存區、全域性/靜態儲存區和常量儲存區。 名稱 特性 棧 由編譯器在需要時自動分配,不需要時自動清除的變數儲存區。通常存放區域性變數、函式引數等。

java中資料型別在中的儲存

1.基本資料型別 eg:int i=1; 基本資料型別都存在棧中,它並沒有建立物件,只是將值放入變數的引用中。 2.引用型別         2.1  String a="abc"; //實際上a是引用變數,"abc"是物件(其實也算不上物

Java中的關係

資料型別     Java虛擬機器中,資料型別可以分為兩類:基本型別和引用型別。基本型別的變數儲存原始值,即:他代表的值就是數值本身;而引用型別的變數儲存引用值。“引用值”代表了某個物件的引用,而不是物件本身,物件本身存放在這個引用值所表示的地址的位置。 基本型別包括:byte,short,int,long

jvm 記憶體 記憶體 大小設定

Tomcat 的JVM 記憶體溢位問題的解決關鍵字: tomcat 的jvm 記憶體溢位問題的解決  最近在熟悉一個開發了有幾年的專案,需要把資料庫從mysql移植到oracle,首先把jdbc的連線指向mysql,打包放到tomcat裡面,可以跑起來,沒有問題,可是當把jdbc連線指向oracle的時

c++記憶體分配方式,區別

1)棧區(stack):由編譯器自動分配釋放 ,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。 2)堆區(heap):一般由程式設計師分配釋放,若程式設計師不釋放,程式結束時可能由OS回收。注意它與資料結構中的堆是兩回事,分配方式倒是類似於連結串列。 3)全域性/靜態區

String s =new String()分析 建立了幾個物件

轉載自 分享最終編輯 tanzhimei393先定義S String str1 = “abc”; System.out.println(str1 == “abc”); 步驟: 1) 棧中開闢一塊空間存放引用str1, 2) String池中開

的記憶體地址相對高低

看下面一段程式碼 #include<bits/stdc++.h> using namespace std; int main() { int a,b; //棧 printf("%x

的區別(經典講解)

摘要:對於堆和棧,很多朋友都是不怎麼理解的,就算是開發了程式多年的朋友都會容易混淆。其實要區分它們並不難,但是怎樣使自己永久不會忘記哪得有技巧了。我相信,通過下面經典的講解,您一定不會再忘記堆和棧的區別了。 對於堆和棧,很多朋友都是不怎麼理解的,就算是開發了程式多年的朋友都會容易混淆。其實要區分它們並不難,