目錄html
按照官方的說法:「Java 虛擬機具備一個堆(Heap),堆是運行時數據區域,全部類實例和數組的內存均今後處分配。堆是在 Java 虛擬機啓動時建立的。」「在JVM中堆以外的內存稱爲非堆內存(Non-heap memory)」。java
JVM主要管理兩種類型的內存:堆和非堆。linux
Heap memory | Code Cache |
Eden Space | |
Survivor Space | |
Tenured Gen | |
non-heap memory | Perm Gen |
native heap?(I guess) |
Java 虛擬機具備一個堆,堆是運行時數據區域,全部類實例和數組的內存均今後處分配。堆是在 Java 虛擬機啓動時建立的。對象的堆內存由稱爲垃圾回收器的自動內存管理系統回收。web
堆的大小能夠固定,也能夠擴大和縮小。堆的內存不須要是連續空間。算法
Java 虛擬機管理堆以外的內存(稱爲非堆內存)。數組
Java 虛擬機具備一個由全部線程共享的方法區。方法區屬於非堆內存。它存儲每一個類結構,如運行時常數池、字段和方法數據,以及方法和構造方法的代碼。它是在 Java 虛擬機啓動時建立的。tomcat
方法區在邏輯上屬於堆,但 Java 虛擬機實現能夠選擇不對其進行回收或壓縮。與堆相似,方法區的大小能夠固定,也能夠擴大和縮小。方法區的內存不須要是連續空間。服務器
除了方法區外,Java 虛擬機實現可能須要用於內部處理或優化的內存,這種內存也是非堆內存。例如,JIT 編譯器須要內存來存儲從 Java 虛擬機代碼轉換而來的本機代碼,從而得到高性能。jvm
PermGen space:全稱是Permanent Generation space,即永久代。就是說是永久保存的區域,用於存放Class和Meta信息,Class在被Load的時候被放入該區域,GC(Garbage Collection)應該不會對PermGen space進行清理,因此若是你的APP會LOAD不少CLASS的話,就極可能出現PermGen space錯誤。工具
Heap space:存放Instance。
Java Heap分爲3個區,Young即新生代,Old即老生代和Permanent。
Young保存剛實例化的對象。當該區被填滿時,GC會將對象移到Old區。Permanent區則負責保存反射對象。
-Xms128m -Xmx256m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m
echo "Using CATALINA_BASE: $CATALINA_BASE"
上面加入如下行:JAVA_OPTS="-server -XX:PermSize=64M -XX:MaxPermSize=128m
設置項 | 說明 |
---|---|
-Xms512m | 表示JVM初始分配的堆內存大小爲512m(JVM Heap(堆內存)最小尺寸,初始分配) |
-Xmx1024m | JVM最大容許分配的堆內存大小爲1024m,按需分配(JVM Heap(堆內存)最大容許的尺寸,按需分配) |
-XX:PermSize=512M | JVM初始分配的非堆內存 |
-XX:MaxPermSize=1024M | JVM最大容許分配的非堆內存,按需分配 |
-XX:NewSize/-XX:MaxNewSize | 定義YOUNG段的尺寸,NewSize爲JVM啓動時YOUNG的內存大小; |
MaxNewSize爲最大可佔用的YOUNG內存大小。 | |
-XX:SurvivorRatio | 設置YOUNG代中Survivor空間和Eden空間的比例 |
-Xmx2000M -Xms2000M -Xmn500M -XX:PermSize=250M -XX:MaxPermSize=250M -Xss256K -XX:+DisableExplicitGC -XX:SurvivorRatio=1 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSClassUnloadingEnabled -XX:LargePageSizeInBytes=128M -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=60 -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+PrintClassHistogram -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -Xloggc:log/gc.log
Java中有四種不一樣的回收算法,對應的啓動參數爲:
–XX:+UseSerialGC –XX:+UseParallelGC –XX:+UseParallelOldGC –XX:+UseConcMarkSweepGC
大部分平臺或者強制 java -client 默認會使用這種。
young generation算法 = serial
old generation算法 = serial (mark-sweep-compact)
這種方法的缺點很明顯, stop-the-world, 速度慢。服務器應用不推薦使用。
在linux x64上默認是這種,其餘平臺要加 java -server 參數纔會默認選用這種。
young = parallel,多個thread同時copy
old = mark-sweep-compact = 1
優勢:新生代回收更快。由於系統大部分時間作的gc都是新生代的,這樣提升了throughput(cpu用於非gc時間)
缺點:當運行在8G/16G server上old generation live object太多時候pause time過長
young = parallel = 2
old = parallel,分紅多個獨立的單元,若是單元中live object少則回收,多則跳過
優勢:old old generation上性能較 parallel 方式有提升
缺點:大部分server系統old generation內存佔用會達到60%-80%, 沒有那麼多理想的單元live object不多方便迅速回收,同時compact方面開銷比起parallel並沒明顯減小。
young generation = parallel collector = 2
old = cms
同時不作 compact 操做。
優勢:pause time會下降, pause敏感但CPU有空閒的場景須要建議使用策略4.
缺點:cpu佔用過多,cpu密集型服務器不適合。另外碎片太多,每一個object的存儲都要經過鏈表連續跳n個地方,空間浪費問題也會增大。
jmap -heap pid using thread-local object allocation. Parallel GC with 4 thread(s) #GC 方式 Heap Configuration: #堆內存初始化配置 MinHeapFreeRatio=40 #對應jvm啓動參數-XX:MinHeapFreeRatio設置JVM堆最小空閒比率(default 40) MaxHeapFreeRatio=70 #對應jvm啓動參數 -XX:MaxHeapFreeRatio設置JVM堆最大空閒比率(default 70) MaxHeapSize=512.0MB #對應jvm啓動參數-XX:MaxHeapSize=設置JVM堆的最大大小 NewSize = 1.0MB #對應jvm啓動參數-XX:NewSize=設置JVM堆的‘新生代’的默認大小 MaxNewSize =4095MB #對應jvm啓動參數-XX:MaxNewSize=設置JVM堆的‘新生代’的最大大小 OldSize = 4.0MB #對應jvm啓動參數-XX:OldSize=<value>:設置JVM堆的‘老生代’的大小 NewRatio = 8 #對應jvm啓動參數-XX:NewRatio=:‘新生代’和‘老生代’的大小比率 SurvivorRatio = 8 #對應jvm啓動參數-XX:SurvivorRatio=設置年輕代中Eden區與Survivor區的大小比值 PermSize= 16.0MB #對應jvm啓動參數-XX:PermSize=<value>:設置JVM堆的‘永生代’的初始大小 MaxPermSize=64.0MB #對應jvm啓動參數-XX:MaxPermSize=<value>:設置JVM堆的‘永生代’的最大大小 Heap Usage: #堆內存分步 PS Young Generation Eden Space: #Eden區內存分佈 capacity = 20381696 (19.4375MB) #Eden區總容量 used = 20370032 (19.426376342773438MB) #Eden區已使用 free = 11664 (0.0111236572265625MB) #Eden區剩餘容量 99.94277218147106% used #Eden區使用比率 From Space: #其中一個Survivor區的內存分佈 capacity = 8519680 (8.125MB) used = 32768 (0.03125MB) free = 8486912 (8.09375MB) 0.38461538461538464% used To Space: #另外一個Survivor區的內存分佈 capacity = 9306112 (8.875MB) used = 0 (0.0MB) free = 9306112 (8.875MB) 0.0% used PS Old Generation #當前的Old區內存分佈 capacity = 366280704 (349.3125MB) used = 322179848 (307.25464630126953MB) free = 44100856 (42.05785369873047MB) 87.95982001825573% used PS Perm Generation #當前的 「永生代」 內存分佈 capacity = 32243712 (30.75MB) used = 28918584 (27.57891082763672MB) free = 3325128 (3.1710891723632812MB) 89.68751488662348% used
JVM內存監控工具
<%@ page import="java.lang.management.*" %> <%@ page import="java.util.*" %> <html> <head> <title>JVM Memory Monitor</title> </head> <body> <table border="0" width="100%"> <tr><td colspan="2" align="center"><h3>Memory MXBean</h3></td></tr> <tr><td width="200">Heap Memory Usage</td><td><%=ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()%></td></tr> <tr><td>Non-Heap Memory Usage</td><td><%=ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()%></td></tr> <tr><td colspan="2"> </td></tr> <tr><td colspan="2" align="center"><h3>Memory Pool MXBeans</h3></td></tr> <% Iterator iter = ManagementFactory.getMemoryPoolMXBeans().iterator(); while (iter.hasNext()) { MemoryPoolMXBean item = (MemoryPoolMXBean) iter.next(); %> <tr><td colspan="2"> <table border="0" width="100%" style="border: 1px #98AAB1 solid;"> <tr><td colspan="2" align="center"><b><%= item.getName() %></b></td></tr> <tr><td width="200">Type</td><td><%= item.getType() %></td></tr> <tr><td>Usage</td><td><%= item.getUsage() %></td></tr> <tr><td>Peak Usage</td><td><%= item.getPeakUsage() %></td></tr> <tr><td>Collection Usage</td><td><%= item.getCollectionUsage() %></td></tr> </table> </td></tr> <tr><td colspan="2"> </td></tr> <%} %> </table> </body> </html>