對於java的這3大區域了解下還是有必要的,尤其是對jvm調優,更應該理解下它們的概念。
堆(heap):專門用來保存對象的實例(new 創建的對象和數組),實際上也只是保存對象實例的屬性值,屬性的類型和對象本身的類型標記等,並不保存對象的方法(方法是指令,保存在Stack中)。
存儲的全部是對象,每個對象都包含一個與之對應的class的信息。(class的目的是得到操作指令);jvm只有一個堆區(heap)被所有線程共享,堆中不存放基本類型和對象引用,只存放對象本身;一般由程式設計師分配釋放, 若程式設計師不釋放,程序結束時可能由OS回收。棧(stack):對象實例在heap 中分配好以後,需要在stack中保存一個4位元組的heap內存地址,用來定位該對象實例在heap 中的位置,便於找到該對象實例。
每個線程包含一個棧區,棧中只保存基礎數據類型的對象和自定義對象的引用(不是對象),對象都存放在堆區中;每個棧中的數據(原始類型和對象引用)都是私有的,其他棧不能訪問;棧分為3個部分:基本類型變量區、執行環境上下文、操作指令區(存放操作指令);由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。靜態區(也叫方法區):跟堆一樣,被所有的線程共享。方法區包含所有的class和static變量。
方法區中包含的都是在整個程序中永遠唯一的元素,如class,static變量;全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域, 未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域。

實際例子:String s1 = new String("China")

對象本身存儲在堆中,常量存儲在靜態區,引用存儲在棧中。
為什麼把堆和棧區分出來呢?
第一:從軟體設計的角度看,棧代表了處理邏輯,而堆代表了數據。這樣分開,使得處理邏輯更為清晰。分而治之的思想。這種隔離、模塊化的思想在軟體設計的方方面面都有體現;
第二:堆與棧的分離,使得堆中的內容可以被多個棧共享(也可以理解為多個線程訪問同一個對象)。這種共享的收益是很多的。一方面這種共享提供了一種有效的數據交互方式(如:共享內存),另一方面,堆中的共享常量和緩存可以被所有棧訪問,節省了空間;
第三:棧因為運行時的需要,比如保存系統運行的上下文,需要進行地址段的劃分。由於棧只能向上增長,因此就會限制住棧存儲內容的能力。而堆不同,堆中的對象是可以根據需要動態增長的,因此棧和堆的拆分,使得動態增長成為可能,相應棧中只需記錄堆中的一個地址即可;
第四:面向對象就是堆和棧的完美結合。其實,面向對象方式的程序與以前結構化的程序在執行上沒有任何區別。但是,面向對象的引入,使得對待問題的思考方式發生了改變,而更接近於自然方式的思考。當我們把對象拆開,你會發現,對象的屬性其實就是數據,存放在堆中;而對象的行為(方法),就是運行邏輯,放在棧中。我們在編寫對象的時候,其實即編寫了數據結構,也編寫的處理數據的邏輯。
理解程序中每一個字符的存儲,才能為我們在jvm中調優做出依據,因為jvm調優也是相對的,解決了一個問題,必然會有第二個問題的潛伏,這就需要我們去衡量如何調優了(任何事情都是有利也有弊)