Java內存管理堆內存棧內存方法區
? ? Java中內存分成兩種,一種叫做棧內存,一種叫做堆內存。還有一個方法區,也叫做靜態區。
1.棧內存中放哪些東西?
①基本類型的變量,例如int a=3中的a;
②對象的引用變量,例如Thread t=new Thread();中的t。
? ? ? 當在代碼塊中定義一個變量時,Java就在棧中為這個變量分配內存空間;當超過變量的作用域后,Java會自動 釋放掉為該變量分配的內存空間,該內存空間可以立刻被另作他用。
2.堆內存中存放哪些東西?
① 存放由new創建的對象和數組。
? ? 在堆中存放的內存,由Java虛擬機垃圾回收器來管理。在堆中產生了一個數組或者對象后,還可以在棧中定義一個特殊的變量,這個變量持有的內容等于數組或者對象在堆內存中的首地址。在棧中的這個特殊的變量,就成了數組或者對象的引用變量,以后就可以在程序中使用棧內存中的引用變量來訪問堆中的數組或者對象,引用變量相當于為數組或者對象起的一個別名,或者代號。
3.靜態區/方法區:
? ? 方法區(method)也叫做靜態區,跟堆一樣,被所有的線程共享。方法區包含所有的class和static變量。
? ? 方法區中包含的都是在整個程序中永遠唯一的元素,例如class,static變量。
? ? 全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域,未初始化的全局變量和未初始化的靜態變量放在相鄰的另一塊區域。
堆內存和棧內存,兩者的區別?
①引用變量是普通變量,定義時在棧內存中分配,引用變量在程序運行到作用域外后被釋放。而數組和對象本身在堆中分配,即使程序運行到使用new產生數組和對象的語句所在的代碼塊之外,數組和對象本身占用的堆內存也不會被釋放。數組和對象在沒有引用變量指向它的時候,才變成垃圾,不能再被使用,但是仍然占著內存,在隨后的一個不確定的時間被垃圾回收器釋放掉,這個也是Java比較占內存的主要原因。實際上,棧中的引用變量指向堆內存中的變量,這就是Java中的指針。
②通俗來講,堆是用來存放對象的,而棧是用來執行程序的。
③jvm只有一個堆區(heap),被所有線程共享;
每個線程包含一個棧區(stack),每個棧中的數據都是私有的,其他的棧不能訪問,但是同一個棧中變量是共享的;分為3個部分:基本類型變量區,執行環境上下文,操作指令區。
為什么要有堆和棧?這樣設計有什么好處?
①Java自動管理堆和棧,程序員不能直接地設置棧和堆。
②Java的堆是一個運行時數據區。堆是由JVM的垃圾回收器自動管理的。堆的優勢是可以在程序運行時,動態地分配內存
大小,但是正是由于這個原因,它的存取速度較慢。
③棧的優勢是,存取速度比堆要快,僅次于寄存器,棧數據可以共享。但缺點是,存在棧中的數據大小和生存期是必須確定的,缺乏靈活性。
? ? 棧有一個很重要的特性,就是存在棧中的數據可以共享。假設我們同時定義:
int a = 3;
int b = 3;
? ? 編譯器先處理int a = 3;首先它會在棧中創建一個變量為a的引用,然后查找棧中是否有3這個值,如果沒找到,就將3存放進來,然后將a指向3。接著處理int b = 3;在創建完b的引用變量后,因為在棧中已經有3這個值,便將b直接指向3。這樣,就出現了a與b同時均指向3的情況。這時,如果再令a=4;那么編譯器會重新搜索棧中是否有4值,如果沒有,則將4存放進來,并令a指向4;如果已經有了,則直接將a指向這個地址。因此a值的改變不會影響到b的值。要注意這種數據的共享與兩個對象的引用時
指向一個對象的這種共享是不同的,因為這種情況a的修改并不會影響到b, 它是由編譯器完成的,它有利于節省空間。而一個對象引用變量修改了這個對象的內部狀態,會影響到另一個對象引用變量。