物理內存RAM(隨機存儲器),寄存單元爲寄存器,用於存儲計算單元執行指令的中間結果。
鏈接處理器和RAM或者處理器和寄存器的是地址總線,這個地址的寬度影響了物理地址的索引範圍,總線的寬度決定了處理器一次能夠從寄存器或者內存中獲取多少個bit。
虛擬內存的出現使不一樣進程在同時運行時能夠共享物理內存,提升內存利用率,並且能擴展內存的地址空間。
一個電腦4GB的地址空間被劃分爲內核空間和用戶空間,程序只能使用用戶空間的內存。
內核空間主要是指操做系統運行時所使用的用於程序調度、虛擬內存的使用或者鏈接硬件資源等的程序邏輯。
Java堆
Java堆是用於存儲Java對象的內存區域,堆的大小在JVM啓動時就一次向操做系統申請完成,經過-Xmx(最大)和-Xms(初始)兩個選項來控制大小,一旦分配完成後就固定了。Java堆中內存空間的管理由JVM來控制,對象建立由Java應用程序控制,對象所佔的空間釋放由管理內存的垃圾收集器來完成。
線程
JVM運行實際程序的實體是線程,而線程須要內存空間來存儲必要的數據。每一個線程建立時JVM都會爲它建立一個堆棧。
類和類的加載器
Java中類和加載類自己一樣須要存儲空間,這個區域叫永久帶(PermGen區)。
卸載類(內存回收)條件:
一、Java堆中沒有對錶示該加載器的java.lang.ClassLoader對象引用
二、Java堆沒有對錶示類加載器的類的任何java.lang.Class對象的引用
三、在Java堆上該類加載器加載的任何類的全部對象都不在存活(被引用)
NIO
NIO使用java.nio.ByteBuffer.allocateDirect()方法分配內存,是本機內存而不是Java堆上的內存,增長了一次系統調用。直接ByteBuffer產生的數據和網絡或者磁盤交互都在操做系統的內核空間中發生,不須要將數據複製到Java內存中,加快數據處理速度。
JNI
JNI技術使得本機代碼(C語言)能夠調用Java方法,即native memory
在Java虛擬機規範中將Java運行時數據劃分爲6種
PC寄存器數據
保存當前執行的程序的內存地址
Java棧
Java棧老是和線程關聯,每當建立一個線程時,JVM就會爲這個線程建立一個對應的Java棧,這個棧中又會含有多個棧幀,這些棧幀是與每一個方法關聯起來,每運行一個方法就建立一個棧幀,每個棧幀會含有一些內存變量,操做棧和方法返回值等信息。
堆
堆是存放Java對象的地方,是JVM管理Java對象的核心內存區域,每一個存儲在堆中的Java對象都是這個對象的類的一個副本,它會複製包括繼承自它父類的全部非靜態屬性
方法區
JVM方法區用於存儲類結構信息的地方,在Java堆中的永久區內,在啓動程序後一段時間就固定餓了
本地方法棧
是爲JVM運行Native方法準備的空間,因爲不少Native方法是C語言實現的,因此也叫C棧
運行時常量池
表明運行時每一個class文件中的常量表
一般的內存分配策略
一、靜態內存分配:指在程序編譯時就能肯定每一個數據在運行時刻的存儲空間需求
二、棧式內存分配(動態存儲分配):由一個相似堆棧的運行棧來實現,程序對數據區的需求在運行時纔可以爲其分配內存。棧式內存分配按照先進後出的原則進行分配
三、堆內存分配:當程序真正運行到相應的代碼時才知道空間大小
Java中內存分配詳解
Java棧:其分配是和線程綁定在一塊兒的,當咱們建立一個線程時,JVM會爲這個線程建立一個新的Java棧,一個線程的方法的調用和返回對應於這個Java棧的壓棧和出棧。當線程激活一個Java方法時,JVM就會在線程的Java堆棧裏新壓入一個幀,這個幀天然成了當前幀。在此方法執行期間,這個幀用來保存參數、局部變量、中間計算過程和其餘數據。棧中主要存放一些基本的數據類型和對象句柄(引用)。存取速度比堆快,僅次於寄存器,棧數據能夠共享。靜態分配內存,編譯時肯定生存期大小。
Java堆:每個Java應用都惟一對應一個JVM實例,每個實例惟一對應一個堆。應用程序在運行中所建立的全部類實例或數組都放在這個堆中,並由應用程序全部的線程共享。Java中分配堆內存是自動初始化,全部對象的存儲空間都是在堆中分配的,可是這個對象的引用在堆棧中分配。可動態分配內存大小、運行時分配內存。
即建立一個對象時,堆中分配的內存實際創建這個對象,而在堆棧中分配的內存只是指向這個堆對象的指針(引用)而已。
靜態內存分配和回收
Java中靜態內存分配指在Java被編譯時就已經可以肯定須要的內存空間,當程序加載時系統把內存一次性分配給它。這些內存只有在程序結束時才被收回。
動態內存分配和回收
Java中對象的內存空間是動態分配的,就是在程序執行時才知道要分配的存儲空間大小,只有等到對象再也不使用時纔會被回收。
如何檢測垃圾
只要某個對象再也不被其餘活動對象引用,那麼這個對象就能夠被回收。活動對象指可以被一個根對象集合到達的對象。
根對象集合:
一、方法中局部變量區中對象的引用
二、Java操做棧中的對象引用
三、常量池中對象引用
四、本地方法中持有的對象引用
五、類的Class對象
基於分代的垃圾收集算法
-
Young區 分爲Eden區和兩個Survivor區,其中新建立的對象都在Eden區,當Eden區滿後觸發minor GC 將Eden區仍然存活的對象複製到Survivor區中,另一個Survivor區中的存活對象也複製到這個Survivor中,保證始終有一個Survivor區是空的。
-
Old區存放的是Young區的Survivor滿後觸發minno GC後仍然存活的對象,當Eden區滿後將對象存放到Survivor區中,若是Survivor中仍然存放不下這些對象,GC收集器會將這些對象直接存放到Old區。若是Survivor區中對象足夠老,也直接存放到Old區。若是Old區也滿了,將會觸發Full GC回收整個堆內存。
-
Perm區存放的主要是類的Class對象,若是一個類被頻繁地加載,也可能會致使Perm區滿,Perm區的垃圾回收也是Full GC觸發的。
三類垃圾收集算法:
一、Serial Collector
是JVM在client模式下的默認的GC方式,經過JVM配置參數-XX:+UseSerialGC來指定GC使用該手機算法。當Eden空間不足時就觸發Minor GC,觸發Minor GC時首先檢查以前每次Minor GC時晉升到Old區的平均對象大小是否大於Old區的剩餘空間,若是大於,則直接觸發Full GC,若是小於,則看HandlePromotionFailur參數的值。若是爲true,僅觸發Minor GC,不然再觸發一次Full GC。
Java參數:java -Xms20M -Xmx20M -Xmn10M -XX:+UseSerialGC -XX:+PrintGCDetails
二、Parallel Collector
Parallel GC根據Minor GC 和Full GC的不一樣分爲三種,分別是ParNewGC、ParallelGC和ParallelOldGC。
1)ParNewGC:經過-XX:+UseParNewGC參數來指定,對象分配和回收策略與Serial Collector相似,只是回收的線程是多線程的。
2)ParallelGC:Server下默認的GC方式,當在Eden區申請內存空間時,若是Eden區不夠,那麼看當前申請的空間是否大於等於Eden的一半,若是大於則此次申請的空間直接在Old中分配,小於則觸發Minor GC。在觸發GC以前首先會檢查每次晉升到Old區的平均大小是否大於Old區的剩餘空間,若是大於則再出發Full GC。在此次觸發GC後仍然會按照這個規則從新檢查一次。
JVM參數:java -Xms20M -Xmx20M -Xmn10M -XX:+UsePaallelGC -XX:+PrintGCDetails
3)ParallelOldGC
和ParallelGC的區別:前者Full GC進行的動做爲清空整個Heap堆中的垃圾對象,清楚Perm區中已經被卸載的類信息,並進行壓縮。然後者是清楚Heap堆中部分垃圾對象,並進行部分的空間壓縮。
三、CMS Collector
觸發規則:檢查Old區或者Perm區的使用率,當達到必定比例時觸發CMS GC,觸發時會回收Old區中的內存空間。觸發Full GC:1)Eden分配失敗,Minor GC後分配到To Space,To
Space不夠再分配到Old區,Old區不夠再出發Full GC 2)當CMS GC正在進行時向Old申請內存失敗則會直接觸發Full GC。
四、三種GC優缺點對比
GC日誌分析
<collector>GC 表示收集器的名稱
<starting occupancy1>表示Young區在GC前佔用的內存。
<ending occupancy1>表示Young區在GC後佔用的內存。
<pause time1>表示Young區局部收集時JVM暫停處理的時間。
<starting occupany2>表示JVM Heap在GC前佔用的內存
<ending occupany2>表示JVM Heap在GC後佔用的內存
<pause time2>表示GC過程當中JVM暫停處理的總時間
根據日誌判斷是否存在內存泄漏,若是<ending occupancy1>-<starting occupany1>=<ending occupancy2>-<starting occupany2>,則代表此次GC對象100%被回收,沒有對象進入Old區或者Perm區。若是是大於號則此次回收對象進入Old區或者Perm區。若是<ending occupany2>一直增加,並且Full GC很頻繁,則可能內存泄漏。