Java虛擬機在執(zhí)行java程序的過程中會把它所管理的內存劃分為若干個不同的數(shù)據(jù)區(qū)域,都有各自的用戶級創(chuàng)建銷毀時間。
堆區(qū)和方法區(qū)是隨著虛擬機進程的啟動一直存在的.
虛擬機棧、本地方法棧和程序計數(shù)器是依賴用戶線程的啟動和結束而創(chuàng)建和銷毀的。

堆 [所有線程共享]
堆區(qū)是JVM管理的內存中最大的一塊,“幾乎”所有的對象實例都在這里分配內存。
堆區(qū)里面又區(qū)分有新生代、老年代。
新生代里又包含1個Eden區(qū)和2個survivor區(qū)【From survivor, To survivor】,
堆里的細分是為了更好的分配和回收內存。
方法區(qū) [所有線程共享]
主要用于存儲加載的類型信息、常量、靜態(tài)變量和即時編譯器編譯后的代碼緩存等數(shù)據(jù)。
在JDK8中已經把里面的永久代給廢棄了,改用本地內存的元空間,這樣就能加載更多的類型信息。
運行時常量池
用于存放編譯期生成的各種字面量與符號引用。
虛擬機棧 [線程私有]
這個也就是我們經常說到的棧區(qū)。在每個方法執(zhí)行的時候都會同步創(chuàng)建一個棧幀,每個棧幀用于存儲局部變量表、操作數(shù)棧、動態(tài)鏈接、方法出口等信息。
每一個方法的執(zhí)行就相當于是壓棧和出棧,在每一個方法執(zhí)行完畢后其對應棧內的數(shù)據(jù)也就隨之被回收了。
所以也就是有些變量我們能夠定義為局部變量的盡量定義在局部變量,方便及時回收。
局部變量表
存放了編譯期可知的數(shù)據(jù)類型、對象引用和返回地址類型。
基本數(shù)據(jù)類型【boolean、byte、char、short 、int、float、long、double】
對象引用:reference類型,不等同于對象本身,可能是一個指向對象起始地址的引用指針,也可能是指向一個代表對象的句柄或者其他于此對象相關的位置。
returnAddress類型:指向了一條字節(jié)碼指令的地址。
上述數(shù)據(jù)類型在局部變量表中的存儲控件以局部變量槽(Slot)來表示,其中64位的long和double類型數(shù)據(jù)會占用2個變量槽,其余的數(shù)據(jù)類型只占用一個。
本地方法棧 [線程私有]
本地方法棧和虛擬機棧其實都一樣,唯一區(qū)別就是這個是提供給本地方法調用使用的,
并且程序計數(shù)器在執(zhí)行本地方法時的指令值是undefined。
程序計數(shù)器 [線程私有]
是一塊較小的內存空間,可以看做是當前線程執(zhí)行的字節(jié)碼行號指示器。[有的地方也叫PC寄存器]
一些基礎功能:
分支、 循環(huán)、跳轉、異常處理和線程恢復等都依靠它來處理。
每個線程都對應著自己唯一的程序計數(shù)器。
計數(shù)器記錄的是正在執(zhí)行的虛擬機字節(jié)碼指令的地址,通過改變計數(shù)器的值來選擇下一步要執(zhí)行的指令。
這是唯一一個在JVM規(guī)范里不會有OOM的區(qū)域。