堆空間算法
Java堆是被全部線程共享的一塊內存區域:主要用於存放對象實例,堆是Java 虛擬機所管理的內存中最大的一塊緩存
爲對象分配內存 = 把一塊大小肯定的內存從堆內存中劃分出來多線程
堆是垃圾收集器管理的主要區域,所以不少時候也被稱作「GC 堆"併發
從堆內存中劃分出來須要的內存的方式:操作系統
問題: 內存分配的併發問題,一是能夠經過原子性操做來避免,二是能夠把內存分配的行爲按照線程進行劃分,在不一樣的空間中進行,每一個線程在Java堆中預先分配一個內存塊,稱爲本地線程分配緩衝(Thread Local Allocation Buffer, TLAB)線程
堆的問題:指針
設置堆的大小對象
堆的大小能夠經過-Xms(最小值)和-Xmx(最大值)參數設置,-Xms爲JVM啓動時申請的最小內存,默認爲操做系統物理內存的1/64但小於1G,-Xmx爲JVM可申請的最大內存,默認爲物理內存的1/4但小於1G內存
如今收集器基本都是採用的分代收集算法,因此Java 堆中還能夠細分爲:新生代和老年代編譯器
新生代:程序新建立的對象都是重新生代分配內存
老年代:用於存放通過屢次新生代GC仍然存活的對象,例如緩存對象,新建的對象也有可能直接進入老年代
棧空間
Java棧是線程私有的,每一個線程對應一個Java棧,每一個線程在執行一個方法時會建立一個對應的棧幀(Stack Frame),棧幀負責存儲局部變量變量表、操做數棧、動態連接和方法返回地址等信息。每一個方法的調用過程,至關於棧幀在Java棧的入棧和出棧過程
方法區:方法區用來存儲類型的元數據信息
方法區和Java堆同樣,是全部線程共享的內存區域,用於存放已被虛擬機加載的類信息、常量、靜態變量和即時編譯器編譯後的代碼等數據。 運行時常量池是方法區的一部分,用於存放編譯期間生成的各類字面常量和符號引用
程序計數器理解
因爲Java 虛擬機的多線程是經過線程輪流切換並分配處理器執行時間的方式來實現的,在任何一個肯定的時刻,一個處理器(對於多核處理器來講是一個內核)只會執行一條線程中的指令。所以,爲了線程切換後能恢復到正確的執行位置,每條線程都須要有一個獨立的程序計數器,各條線程之間的計數器互不影響,獨立存儲,咱們稱這類內存區域爲「線程私有」的內存。
若是線程正在執行的是一個Java 方法,這個計數器記錄的是正在執行的虛擬機字節碼指令的地址;若是正在執行的是Natvie 方法,這個計數器值則爲空(Undefined)。
內存溢出和內存泄漏
內存溢出 out of memory,是指程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory;好比申請了一個integer,但給它存了long才能存下的數,那就是內存溢出。 內存泄露 memory leak,是指程序在申請內存後,沒法釋放已申請的內存空間,一次內存泄露危害能夠忽略,但內存泄露堆積後果很嚴重,不管多少內存,早晚會被佔光。 memory leak會最終會致使out ofmemory。
例子
new一個對象的過程:A a = new A();
3.在方法區中,存放的都是惟一的整個程序中惟一的元素,例如static變量。