棧(stack)與堆(heap)都是Java用來在Ram中存放數據的地方。Java自動管理棧和堆,程序員不能直接地設置棧或堆。html
理解:java
棧是操做系統在創建某個進程或者線程(在支持多線程的操做系統中是線程)爲這個線程創建的存儲區域,該區域具備先進後出的特性。程序員
棧內存用來存儲局部變量和方法調用(其實這算是實際運行時JVM提供的性能優化)數組
//若是該局部變量是基本數據類型,那麼直接將該值存儲在棧中 int a=1; //若是該局部變量是一個對象,那麼將引用存在棧中,而對象{1,2}存儲在堆內 int[] array=new int[]{1,2};
特色:多線程
1). 存取速度比堆要快(不明顯),僅次於直接位於CPU中的寄存器。 2). 棧中的數據能夠共享(也就是說,棧中的數據能夠被多個變量共同引用)
缺點:存在棧中的數據大小與生存期必須是肯定的,缺少靈活性jvm
異常錯誤:若是棧內存沒有可用的空間存儲方法調用和局部變量,JVM會拋出java.lang.StackOverFlowError。性能
每一個Java應用都惟一對應一個JVM實例,每個JVM實力惟一對應一個堆。優化
應用程序在運行中所建立的全部類實例都放在這個堆中,並有應用全部的線程共享。操作系統
Java中分配堆內存是自動初始化的,Java中全部對象的存儲空間都是在堆中分配的,但這些對象的引用則是在棧中分配的,也就是說,通常創建一個對象是,堆和棧都會分配內存
特色:能夠動態的分配內存大小,生存期也沒必要實現告訴編譯器,在堆中分配的內存,有Java虛擬機的垃圾收集器(GC)來管理。
缺點:因爲要在運行時動態分配內存,存取速度較慢
異常錯誤:而若是是堆內存沒有可用的空間存儲生成的對象,JVM會拋出java.lang.OutOfMemoryError。
在堆中產生了一個數組或對象後,還能夠在棧中定義一個特殊的變量,讓棧中這個變量的取值等於數組或對象在堆內存中的首地址,棧中的這個變量結成了數組或對象的引用變量。
引用變量就至關因而爲數組或對象起的一個名稱,之後就能夠在程序中使用棧中的引用變量來訪問堆中的數組或對象。
引用變量就是普通變量,定義時在棧中分配內存,引用變量在程序運行到做用域外釋放。而數組或對象自己在堆中分配,即便程序運行到使用new產生數組或對象的語句以外,他佔用的堆內存也不會被釋放。
也就是說,數組和對象在沒有引用變量指向它的時候,才變成垃圾,不能在被使用,但這時依然佔用這內存,以後會在一個不肯定的時間唄垃圾回收器釋放掉。
速度依次遞減
這是最快的存儲區,由於它位於不一樣與其餘存儲區的地方——處理器內部。可是寄存器的數量極其有限,因此寄存器由編譯器根據需求進行分配。你不能直接控制,也不能在程序中感受寄存器存在的任何跡象
位於通用RAM中,但經過他的「堆棧指針」能夠從處理器那裏得到支持。
堆棧指針若向下移動,則分配新的內存;若向上移動,則釋放那些內存。這是一種快速有效的分配存儲方式,僅次於寄存器。
建立程序的時候,Java編譯器必須知道存儲在堆棧內全部數據的確切大小和生命週期,由於它必須生成相應的代碼,以便上下移動堆棧指針。這一約束限制了程序的靈活性,因此雖然某些Java數據存儲在棧內存中(特別是對象引用),可是Java的對象不存儲其中。
一種通用型內存池,也位於RAM中,用於存放Java對象。
堆不一樣於棧的好處是,編譯器不須要知道要從堆裏分配多少存儲空間,也不須要知道存儲的數據在堆裏存活多長時間,所以,在對立分配存儲有很大的靈活性。
當你建立一個對象時,會自動在對立進行存儲分配。但堆進行存儲分配會比用棧進行存儲須要更多的時間
這裏的靜態是指「在固定的位置」,也是位於RAM,靜態存儲裏存放程序運行時一直存在的數據。可用static關鍵字來標識一個對象的特定元素時靜態的,但對象自己時不會存放在靜態存儲空間的。
常量一般直接置於程序代碼內部。由於他們永遠都不會改變,有的常量須要嚴格的保護,因此能夠將他們置於只讀存儲器中。
若是數據徹底存活於程序以外,那麼他能夠不受程序的任何控制,甚至在程序沒有運行時也能夠存在。
每一個線程包含本身的一個棧區,棧中只保存局部變量和方法調用。
每一個棧的數據都是私有的,其餘棧不可訪問。
棧 = 基本類型變量區 + 執行環境上下文 + 操做指令區(存放操做指令)
存儲的是對象,每一個對象都包含一個與之對應的class信息(Clazz.getClass())獲取,class的目的是獲得操做指令。
JVM只有一個堆區,被全部線程共享,堆中只存放對象自己
又稱靜態區,被全部線程共享,
方法去包含全部的class和static變量