『壹』 怎麼查看GC 及jvm配置
JVisualVM是JDK 6 update 7之後推出的一個工具,它類似於JProfiler的工具,基於此工具可查看內存的消耗情況、線程的執行狀況及程序中消耗CPU、內存的動作。
『貳』 Tomcat GC Log,怎麼看GC有沒有問題,每個參數都是什麼意思。伺服器突然掛了,log沒有里任何異常信息!
98277.469: [GC 98277.469: [ParNew: 724452K->49066K(853376K), 0.0701960 secs] 841423K->166244K(1877376K), 0.0707240 secs] [Times: user=0.54 sys=0.00, real=0.07 secs]
ParNew垃圾回收器的類型,這個是處理新生代的,724452K->49066K清理前後的大小。(853376K)總大小,0.0701960 secs 消耗時間
841423K->166244K(1877376K), 0.0707240 secs zhege 可能就是老年代的回收了。也是大小,時間。
[Times: user=0.59 sys=0.00, real=0.08 secs] 這個就不清楚了。第一個猜測可能是服務暫停響應時間吧。
從給出的日誌好像看不出問題啊。
『叄』 eclipse設置查看GC日誌和如何理解GC日誌
1. Run as -> Run configurations -> java應用名 -> arguments ->VM arguments,加入jvm參數就行
2. 測試代碼
[java]view plain
packagecn.erong.test;
publicclassJtest{
privatestaticfinalint_1M=1024*1024;
publicstaticvoidmain(String[]args){
byte[]allocation1,allocation2,allocation3,allocation4;
allocation1=newbyte[_1M/4];
allocation2=newbyte[_1M/4];
allocation3=newbyte[4*_1M];
allocation4=newbyte[4*_1M];
allocation4=null;
allocation4=newbyte[4*_1M];
}
}
3. 測試看下,在vm arguments 中加入
[java]view plain
-Xms20m--jvm堆的最小值
-Xmx20m--jvm堆的最大值
-XX:+PrintGCTimeStamps--列印出GC的時間信息
-XX:+PrintGCDetails--列印出GC的詳細信息
-verbose:gc--開啟gc日誌
-Xloggc:d:/gc.log--gc日誌的存放位置
-Xmn10M--新生代內存區域的大小
-XX:SurvivorRatio=8--新生代內存區域中Eden和Survivor的比例
4 . run 看下日誌,到d盤找到 gc.log,如下
[plain]view plain
JavaHotSpot(TM)ClientVM(25.151-b12)forwindows-x86JRE(1.8.0_151-b12),builtonSep5201719:31:49by"java_re"withMSVC++10.0(VS2010)
Memory:4kpage,physical3567372k(982296kfree),swap7133056k(3042564kfree)
CommandLineflags:-XX:InitialHeapSize=20971520-XX:MaxHeapSize=20971520-XX:MaxNewSize=10485760-XX:NewSize=10485760-XX:+PrintGC-XX:+PrintGCDetails-XX:+PrintGCTimeStamps-XX:SurvivorRatio=8-XX:-
0.091:[GC(AllocationFailure)0.091:[DefNew:5427K->995K(9216K),0.0036445secs]5427K->5091K(19456K),0.0038098secs][Times:user=0.00sys=0.02,real=0.00secs]
0.095:[GC(AllocationFailure)0.095:[DefNew:5091K->0K(9216K),0.0012412secs]9187K->5090K(19456K),0.0012908secs][Times:user=0.00sys=0.00,real=0.00secs]
Heap
defnewgenerationtotal9216K,used4260K[0x04000000,0x04a00000,0x04a00000)
edenspace8192K,52%used[0x04000000,0x044290e8,0x04800000)
fromspace1024K,0%used[0x04800000,0x04800000,0x04900000)
tospace1024K,0%used[0x04900000,0x04900000,0x04a00000)
tenuredgenerationtotal10240K,used5090K[0x04a00000,0x05400000,0x05400000)
thespace10240K,49%used[0x04a00000,0x04ef8ac0,0x04ef8c00,0x05400000)
Metaspaceused84K,capacity2242K,committed2368K,reserved4480K
『肆』 如何查看GC 及jvm配置
java雖然是自動回收內存,但是應用程序,尤其伺服器程序最好根據業務情況指明內存分配限制。否則可能導致應用程序宕掉。
舉例說明含義:
-Xms128m
表示JVM Heap(堆內存)最小尺寸128MB,初始分配
-Xmx512m
表示JVM Heap(堆內存)最大允許的尺寸256MB,按需分配。
說明:如果-Xmx不指定或者指定偏小,應用可能會導致java.lang.OutOfMemory錯誤,此錯誤來自JVM不是Throwable的,無法用try...catch捕捉。
PermSize和MaxPermSize指明虛擬機為java永久生成對象(Permanate generation)如,class對象、方法對象這些可反射(reflective)對象分配內存限制,這些內存不包括在Heap(堆內存)區之中。
-XX:PermSize=64MB 最小尺寸,初始分配
-XX:MaxPermSize=256MB 最大允許分配尺寸,按需分配
過小會導致:java.lang.OutOfMemoryError: PermGen space
MaxPermSize預設值和-server -client選項相關。
-server選項下默認MaxPermSize為64m
-client選項下默認MaxPermSize為32m
經驗:
1、慎用最小限制選項Xms,PermSize已節約系統資源。
=========================================================
近期研究對jvm的內存使用情況進行監控,因此對觀察虛擬機的內存使用方法做了一些收集,對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區則負責保存反射對象。
幾個參數設置的意義:
xms/xmx:定義YOUNG+OLD段的總尺寸,ms為JVM啟動時YOUNG+OLD的內存大小;mx為最大可佔用的YOUNG+OLD內存大小。在用戶生產環境上一般將這兩個值設為相同,以減少運行期間系統在內存申請上所花的開銷。
NewSize/MaxNewSize:定義YOUNG段的尺寸,NewSize為JVM啟動時YOUNG的內存大小;MaxNewSize為最大可佔用的YOUNG內存大小。在用戶生產環境上一般將這兩個值設為相同,以減少運行期間系統在內存申請上所花的開銷。
PermSize/MaxPermSize:定義Perm段的尺寸,PermSize為JVM啟動時Perm的內存大小;MaxPermSize為最大可佔用的Perm內存大小。在用戶生產環境上一般將這兩個值設為相同,以減少運行期間系統在內存申請上所花的開銷。
SurvivorRatio:設置YOUNG代中Survivor空間和Eden空間的比例
申請一塊內存的過程:
A. JVM會試圖為相關Java對象在Eden中初始化一塊內存區域
B. 當Eden空間足夠時,內存申請結束。否則到下一步
C. JVM試圖釋放在Eden中所有不活躍的對象(這屬於1或更高級的垃圾回收);釋放後若Eden空間仍然不足以放入新對象,則試圖將部分Eden中活躍對象放入Survivor區/OLD區
D. Survivor區被用來作為Eden及OLD的中間交換區域,當OLD區空間足夠時,Survivor區的對象會被移到Old區,否則會被保留在Survivor區
E. 當OLD區空間不夠時,JVM會在OLD區進行完全的垃圾收集(0級)
F. 完全垃圾收集後,若Survivor及OLD區仍然無法存放從Eden復制過來的部分對象,導致JVM無法在Eden區為新對象創建內存區域,則出現」out of memory錯誤」
我們的一種resin伺服器的jvm參數設置:
「-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:=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
1. Serial Collector
大部分平台或者強制 java -client 默認會使用這種。
young generation演算法 = serial
old generation演算法 = serial (mark-sweep-compact)
這種方法的缺點很明顯,stop-the-world, 速度慢。伺服器應用不推薦使用。
2. Parallel Collector
在linux x64上默認是這種,其他平台要加 java -server 參數才會默認選用這種。
young = parallel,多個thread同時
old = mark-sweep-compact = 1
優點:新生代回收更快。因為系統大部分時間做的gc都是新生代的,這樣提高了throughput(cpu用於非gc時間)
缺點:當運行在8G/16G server上old generation live object太多時候pause time過長
3. Parallel Compact Collector (ParallelOld)
young = parallel = 2
old = parallel,分成多個獨立的單元,如果單元中live object少則回收,多則跳過
優點:old old generation上性能較 parallel 方式有提高
缺點:大部分server系統old generation內存佔用會達到60%-80%, 沒有那麼多理想的單元live object很少方便迅速回收,同時compact方面開銷比起parallel並沒明顯減少。
4. Concurent Mark-Sweep(CMS) Collector
young generation = parallel collector = 2
old = cms
同時不做 compact 操作。
優點:pause time會降低, pause敏感但CPU有空閑的場景需要建議使用策略4.
缺點:cpu佔用過多,cpu密集型伺服器不適合。另外碎片太多,每個object的存儲都要通過鏈表連續跳n個地方,空間浪費問題也會增大。
內存監控的方法:
1. jmap -heap pid
查看java 堆(heap)使用情況
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
=====================================================================
jps
-q只輸出進程ID,而不輸出類的短名稱
-m用於輸出傳遞給Java進程(主函數)的參數
-l完整路徑
-v顯示傳遞給jvm的參數
『伍』 gc日誌如何查看哪些
要查看GC日誌首先要知道GC的log放在哪裡,使用jps命令查看當前有哪些java進程在運行,找到我們要查看的java程序的進程pid
使用命令jinfo pid 來查看這個進程對應的java 信息,可以看到大概在最下面的地方有個參數-Xloggc:,他對應的就是gc log的位置。
用gcviewer 打開gc log可以很直觀的查看gc log:
第一個標簽頁就是Chart,這也是最可以直觀看出有沒有問題的地方,如上圖所示,這個日誌反應了gc一直在不停的做新生帶的回收,並且老年代的使用率一直在增加。圖中整個高度為JVM總的內存大小,也就是989.9M,從右側的Summary也可以看出。其中的紫色部分為老年代的大小,黃色部分是新生帶的大小。不同顏色的線和圖塊的含義可以從菜單看出,如下圖:
『陸』 如何開啟gc日誌
進入到了tomcat的bin的目錄下中,命令中vi catalina.sh 來編輯
然後在該文件中添加為
JAVA_OPTS="-Xms128m -Xmx256m -Xmn100m -XX:MaxPermSize=30m -Xloggc:/usr/local/tomcat/logs/gc.$$.log"
gc開啟完成之後,只要啟動了tomcat之後,就可目錄下生成了gc的log的日誌內容。
為了能方便中進行分析的話,需要把Linux中gc日誌拷貝到windows本地種。
進行打開hpjtune的jar的文件,來分析gc的文件。
打開了hpjtune的之後,點擊打開文件,
瀏覽gc的日誌的文件,並選中之後,點擊打開。
這樣話可以分析gc的具體的內容了。
『柒』 理解CMS GC日誌
本文以idea的啟動日誌為例解讀CMS收集器的GC日誌
在 idea64.exe.vmoptions 文件中可以看到idea的啟動參數,下面是初始啟動參數配置
其中 -XX:+UseConcMarkSweepGC 表示使用 ParNew + CMS + Serial Old 收集器組合進行內存回收,Serial收集器是作為CMS收集器出現Concurrent Model Failure失敗後的後備收集器,相當於替補。
接下來需要添加啟動參數來列印idea的GC日誌,JVM提供的幾個主要的GC日誌參數如下:
綜上,我們在 idea64.exe.vmoptions 文件中添加如下配置參數列印GC信息
然後重啟idea,就能在對應的D盤根目錄下找到生成的gc.log日誌。
由於日誌內容過長,一下子全展示出來太亂而不方便閱讀,這里對日誌中每個不用的現象輸出分別做出講解。
首先文件的最開頭的信息如下:
這個很好理解,就是顯示了當前程序運行的環境,當前的jdk版本為1.8。
接下來的輸出信息如下:
這部分顯示了這次JVM的啟動參數配置,我們在idea64.exe.vmoptions配置的信息也會在這里列印出來,我們可以從這里看出很多默認配置,比如 -XX:MaxTenuringThreshold=6 這個參數,表示Survivor區的對象晉升老年代的年齡閾值為6,這個值在JDK 1.8之前默認為15。
再下面就是應用的GC信息了,不同的內存區域(新生代和老年代)發生的GC日誌信息有所不同,下面一一舉例。
最前面的 2019-03-01T13:38:04.037+0800: 0.867: 是固定的, 2019-03-01T13:38:04.037+0800 表示GC發生的日期花間, 0.867 表示本次gc與JVM啟動時的相對時間,單位為秒。
[GC (Allocation Failure) 這里的 GC 表示這是一次垃圾回收,但並不能單憑這個就判斷這是依次Minor GC,下文會說到CMS的標識為 [GC (CMS Initial Mark) 和 [GC (CMS Final Remark) ,同樣是 GC CMS的卻是是Major GC;括弧中的 Allocation Failure 表示gc的原因,新生代內存不足而導致新對象內存分配失敗。
再後面的 [ParNew: 表示本次gc使用的垃圾收集器為ParNew,我們知道ParNew是針對新生代的垃圾收集器,從這可以看出本次gc是Minor GC。後面緊跟著的 34944K->4352K(39296K) 的含義是 GC前該內存區域已使用容量 -> GC後該內存區域已使用容量(該內存區域總容量) ,再後面的 0.0138186 secs 表示該內存區域GC所佔用的時間,單位為秒。
再後面的 34944K->6355K(126720K), 0.0141834 secs 表示收集前後整個堆的使用情況, 0.0141834 secs 表示本次GC的總耗時,包括把年輕代的對象轉移到老年代的時間。
最後的 [Times: user=0.06 sys=0.00, real=0.02 secs] 表示GC事件在不同維度的耗時,單位為秒。這裡面的user、sys和real與Linux的time命令所輸出的時間含義一致,分別表示用戶態消耗的CPU時間、內核態消耗的CPU時間和操作從開始到結束所經過的等待耗時,例如等待磁碟I/O、等待線程阻塞,而CPU時間不包括這些耗時,但當系統有多CPU或者多核的話,多線程操作會疊加這些CPU時間,所以有時候user或sys時間超過real時間也是完全正確的。
這里先要明確Minor GC、Major GC和Full GC的區別:
老年代由CMS收集器執行的Major GC相對比較復雜,包括初始標記、並發標記、重新標記和並發清除4個階段,下面的gc日誌也詳細地描述了各個階段的信息。
為了更清晰的觀察各個階段的日誌信息,對上面的日誌信息重新排版並添加註釋,如下:
下面對上圖中各個階段的日誌進行分析
初始標記階段(CMS initial mark)
[GC (CMS Initial Mark) 表示這是CMS開始對老年代進行垃圾圾收集的初始標記階段,該階段從垃圾回收的「根對象」開始,且只掃描直接與「根對象」直接關聯的對象,並做標記,需要暫停用戶線程(Stop The Word,下面統稱為STW),速度很快。 104208K(126116K) 表示當前老年代的容量為126116K,在使用了104208K時開始進行CMS垃圾回收。可以計算下這個比例,104208 / 126116約等於0.83,可以大概推算出CMS收集器的啟動內存使用閾值。
後面的 108824K(165412K), 0.0055322 secs 表示當前整個堆的內存使用情況和本次初始標記耗費的時間,最後的 [Times: user=0.00 sys=0.00, real=0.00 secs] 上文已經講過,下文將不再重復。
並發標記階段(CMS concurrent mark)
該階段進行了細分,但都是和用戶線程並發進行的
[CMS-concurrent-mark 表示並發標記階段,會遍歷整個年老代並且標記活著的對象,後面的 0.154/0.155 secs 表示該階段持續的時間和時鍾時間,耗時0.15秒,可見耗時是比較長的。
由於該階運行的過程中用戶線程也在運行,這就可能會發生這樣的情況,已經被遍歷過的對象的引用被用戶線程改變,如果發生了這樣的情況,JVM就會標記這個區域為Dirty Card。
[CMS-concurrent-preclean 階段會把上一個階段被標記為Dirty Card的對象以及可達的對象重新遍歷標記,完成後清楚Dirty Card標記。另外,一些必要的清掃工作也會做,還會做一些final remark階段需要的准備工作。
[CMS-concurrent-abortable-preclean 並發預清理,這個階段嘗試著去承擔接下來STW的Final Remark階段足夠多的工作,由於這個階段是重復的做相同的事情直到發生aboart的條件(比如:重復的次數、多少量的工作、持續的時間等等)之一才會停止。這個階段很大程度的影響著即將來臨的Final Remark的停頓。
從後面的 1.190/1.707 secs 顯示這個階段持續了1秒多的時間,相當的長。
重新標記階段(CMS remark)
該階段同樣被細分為多個子階段
[GC (CMS Final Remark) 表示這是CMS的重新標記階段,會STW,該階段的任務是完成標記整個年老代的所有的存活對象,盡管先前的pre clean階段盡量應對處理了並發運行時用戶線程改變的對象應用的標記,但是不可能跟上對象改變的速度,只是為final remark階段盡量減少了負擔。
[YG occupancy: 24305 K (39296 K)] 表示年輕代當前的內存佔用情況,通常Final Remark階段要盡量運行在年輕代是足夠干凈的時候,這樣可以消除緊接著的連續的幾個STW階段。
[Rescan (parallel) , 0.0103714 secs] 這是整個final remark階段掃描對象的用時總計,該階段會重新掃描CMS堆中剩餘的對象,重新從「根對象」開始掃描,並且也會處理對象關聯。本次掃描共耗時 0.0103714s。
[weak refs processing, 0.0006267 secs] 第一個子階段,表示對弱引用的處理耗時為0.0006267s。
[class unloading, 0.0368915 secs] 第二個子階段,表示卸載無用的類的耗時為0.0368915s。
[scrub symbol table, 0.0486196 secs] 最後一個子階段,表示清理分別包含類級元數據和內部化字元串的符號和字元串表的耗時。
[1 CMS-remark: 108093K(126116K)] 表示經歷了上面的階段後老年代的內存使用情況。再後面的 132398K(165412K), 0.1005635 secs 表示final remark後整個堆的內存使用情況和整個final remark的耗時。
並發清除階段(CMS concurrent sweep)
該階段和用戶線程並發執行,不會STW,作用是清除之前標記階段沒有被標記的無用對象並回收內存。整個過程分為兩個子階段。
CMS-concurrent-sweep 第一個子階段,任務是清除那些沒有標記的無用對象並回收內存。後面的參數是耗時,不再多提。
CMS-concurrent-reset 第二個子階段,作用是重新設置CMS演算法內部的數據結構,准備下一個CMS生命周期的使用。
這里再講一個小知識點,我們上面提到CMS收集器會在老年代內存使用到一定程度時就觸發垃圾回收,這是因為CMS收集器的一個缺陷導致的這種設定,也就是無法處理「浮動垃圾」,「浮動垃圾」就是指標記清除階段用戶線程運行產生的垃圾,而這部分對象由於沒有做標記處理所以在本次CMS收集中是無法處理的。如果CMS是在老年代空間快用完時才啟動垃圾回收,那很可能會導致在並發階段由於用戶線程持續產生垃圾而導致老年代內存不夠用而導致「Concurrent Mode Failure」失敗,那這時候虛擬機就會啟用後備預案,臨時啟用Serial Old收集器來重新進行老年代的垃圾收集,Serial Old是基於「標記-整理」演算法的單線程收集器,這樣停頓時間就會很長。這個CMS啟動的內存使用閾值可以通過參數 -XX: 來設置,默認為68%(這是網上查到的數據),不過這68%應該是JDK1.8之前版本的默認參數,因為上文中初始標記階段的gc日誌分析中顯示老年代內存使用到了83%才開始的CMS垃圾收集。我通過在命令行輸入 java -XX:+PrintFlagsInitial 命令查看到的本機參數如下,也不知道這-1是什麼意思,隨機?如果你知道,可以在文章下留言告知,十分感謝!
由於元空間內存不足而引發的Full GC
這里還有一種Full GC日誌也比較容易出現,如下:
通過 [Full GC (Metadata GC Threshold) 我們知道這是一次針對整個堆(包括年輕代和老年代)的Full GC,括弧中的 Metadata GC Threshold 說明了gc發生的原因,是因為元空間內存不足夠而產生擴容導致的GC,同樣的我們還可以通過後面的 [CMS: 0K->19938K(1048576K) 看出在老年代內存使用為0的時候就發生了Full GC,所以可以確定不是因為老年代內存不夠用而發生的gc。
再後面的 [Metaspace: 20674K->20674K(1069056K)] 表示這次gc前後的元空間(Metaspace)內存變化,元空間的最大容量為1069056K,約等於1G,疑問便來了,最大容量為1G,已使用才20670K,為什麼會不夠用?
從JDK8開始,方法區採用元空間(Metaspace)的概念來實現,原來的永久代(PermGen)實現被廢棄。元空間並不在虛擬機中,而是使用本地內存,默認情況下,元空間的大小僅受本地內存限制。可以通過下面的參數來指定元空間的大小:
還有幾個參數也值得我們關註:
所以我們只要根據實際情況將元空間的初始值設置的大一點就可以避免這種Full GC。
程序中調用System.gc()而引發的Full GC
還有一種gc日誌,雖然不多見,但也在我這次啟動中出現了,如下
[Full GC (System.gc()) 說明這是一次Full GC,是由於調用System.gc()觸發的。
後面的 [CMS: 114245K->129265K(536576K) 表示這次gc後老年代內存佔用由114245K上漲到了 129265K ,注意,這並不能說明沒有對老年代進行回收;再後面的 378366K->129265K(997376K) 表示這次gc後整個堆空間大小縮小到了 129265K ,正好等於老年代的使用量,所以可以推斷這次Full GC回收了年輕代的內存,並將存活的對象全部移到了老年代。
為了更清楚的看清這次gc前後各個內存區域的內存佔用變化,在啟動參數中加入 -XX:+PrintHeapAtGC 參數列印GC前後的堆內存信息,重啟idea,同樣發生了這種gc,如下:
紅框部分的現象跟上面的現象差不多,紅框上面是gc前堆中各區域的使用情況,紅框下面是gc後堆中各區域的使用情況,可以看出這次gc後新生代確實被清空了(eden、form和to區使用量都為0%),老年代佔用內存變大,再反觀之前的由於元空間內存不足而發生的Full GC同樣也是清空了年輕代,由此可以推論出Full GC會對整個堆進行垃圾回收,並且會將年輕代存活的對象全部轉移到老年代。
本文章解讀了jdk1.8版本下idea採用CMS收集器時的啟動gc日誌信息,閱讀完這篇文章後能對GC日誌有個大體的認識,通過對GC日誌的分析可以幫助你更加清晰深入的理解JVM的內存分布,以及垃圾收集的具體細節。不同垃圾收集方案下的gc日誌會有所不同,但也都大同小異。
『捌』 怎樣查看linux cache內容
一、Linux下查看CPU Cache級數,每級大小
(1) 第一種方法:
dmesg | grep cache
(2) 第二種方法:
[root@gc15 ~]# ls /sys/devices/system/cpu/cpu0/cache/index
index0/ index1/ index2/ index3/
一級cache, Data cache
index0和Index1是一級cache中的data和instruction cache
[root@gc15 ~]# cat /sys/devices/system/cpu/cpu0/cache/index0/level
1
[root@gc15 ~]# cat /sys/devices/system/cpu/cpu0/cache/index0/type
Data
[root@gc15 ~]# cat /sys/devices/system/cpu/cpu0/cache/index0/size
32K
一級cache, Instruction cache
[root@gc15 ~]# cat /sys/devices/system/cpu/cpu0/cache/index1/level
1
[root@gc15 ~]# cat /sys/devices/system/cpu/cpu0/cache/index1/type
Instruction
[root@gc15 ~]# cat /sys/devices/system/cpu/cpu0/cache/index1/size
32K
二級cache,共享的
[root@gc15 ~]# cat /sys/devices/system/cpu/cpu0/cache/index2/level
2
[root@gc15 ~]# cat /sys/devices/system/cpu/cpu0/cache/index3/type
Unified
[root@gc15 ~]# cat /sys/devices/system/cpu/cpu0/cache/index2/size
256K
三級cache,共享的
[root@gc15 ~]# cat /sys/devices/system/cpu/cpu0/cache/index3/level
3
[root@gc15 ~]# cat /sys/devices/system/cpu/cpu0/cache/index3/type
Unified
[root@gc15 ~]# cat /sys/devices/system/cpu/cpu0/cache/index3/size
12288K
『玖』 linux下.fa文件怎樣用python求GC含量
在Python中,為了解決內存泄露問題,採用了對象引用計數,並基於引用計數實現自動垃圾回收。
由於Python 有了自動垃圾回收功能,就造成了不少初學者誤認為不必再受內存泄漏的騷擾了。但如果仔細查看一下Python文檔對 __del__() 函數的描述,就知道這種好日子裡也是有陰雲的。下面摘抄一點文檔內容如下:
Some common situations that may prevent the reference count of an object from going to zero include: circular references between objects (e.g., a doubly-linked list or a tree data structure with parent and child pointers); a reference to the object on the stack frame of a function that caught an exception (the traceback stored in sys.exc_traceback keeps the stack frame alive); or a reference to the object on the stack frame that raised an unhandled exception in interactive mode (the traceback stored in sys.last_traceback keeps the stack frame alive).
可見,有 __del__() 函數的對象間的循環引用是導致內存泄漏的主凶。但沒有__del__()函數的對象間的循環引用是可以被垃圾回收器回收掉的。
如何知道一個對象是否內存泄露掉了呢?
可以通過Python的擴展模塊gc來查看不能回收掉的對象的詳細信息。
『拾』 查看linuxgc日誌,求助,GC和GC有什麼區別啊GC和GC有什麼區
java雖然是自動回收內存,但是應用程序,尤其伺服器程序最好根據業務情況指明內存分配限制。否則可能導致應用程序宕掉。 舉例說明含義: -Xms128m 表示JVM Heap(堆內存)最小尺寸128MB,初始分配 -Xmx512m 表示JVM Heap(堆內存)最大允許的尺寸256