先問問題主GC是啥玩意?
首先,樓主需明白JVM 內置的通用垃圾回收原則,堆內存劃分為 Eden、Survivor 和 Tenured/Old 空間,推薦去看《深入理解Java虛擬機》。GC一共分三種:MinorGC,
Major GC v和Full GC
Minor GC
從年輕代空間(包括 Eden 和 Survivor 區域)回收內存被稱為 Minor GC。這一定義既清晰又易于理解。但是,當發生Minor GC事件的時候,有一些有趣的地方需要注意到:
當 JVM 無法為一個新的對象分配空間時會觸發 Minor GC,比如當 Eden 區滿了。所以分配率越高,越頻繁執行 Minor GC。
內存池被填滿的時候,其中的內容全部會被復制,指針會從0開始跟蹤空閑內存。Eden 和 Survivor 區進行了標記和復制操作,取代了經典的標記、掃描、壓縮、清理操作。所以 Eden 和 Survivor 區不存在內存碎片。寫指針總是停留在所使用內存池的頂部。
執行 Minor GC 操作時,不會影響到永久代。從永久代到年輕代的引用被當成 GC roots,從年輕代到永久代的引用在標記階段被直接忽略掉。
質疑常規的認知,所有的 Minor GC 都會觸發“全世界的暫停(stop-the-world)”,停止應用程序的線程。對于大部分應用程序,停頓導致的延遲都是可以忽略不計的。其中的真相就 是,大部分 Eden 區中的對象都能被認為是垃圾,永遠也不會被復制到 Survivor 區或者老年代空間。如果正好相反,Eden 區大部分新生對象不符合 GC 條件,Minor GC 執行時暫停的時間將會長很多。
所以 Minor GC 的情況就相當清楚了——每次 Minor GC 會清理年輕代的內存。
Major GC vs Full GC
大家應該注意到,目前,這些術語無論是在 JVM 規范還是在垃圾收集研究論文中都沒有正式的定義。但是我們一看就知道這些在我們已經知道的基礎之上做出的定義是正確的,Minor GC 清理年輕帶內存應該被設計得簡單:
Major GC 是清理永久代。
Full GC 是清理整個堆空間—包括年輕代和永久代。
很不幸,實際上它還有點復雜且令人困惑。首先,許多 Major GC 是由 Minor GC 觸發的,所以很多情況下將這兩種 GC 分離是不太可能的。另一方面,許多現代垃圾收集機制會清理部分永久代空間,所以使用“cleaning”一詞只是部分正確。
有時候系統會頻繁的FullGC,這時候需要去服務器查一下原因,當然這又是另一個問題,樓主可以自己去了解下。