JVM調優實戰——YoungGC的優化過程

問題

在這裏插入圖片描述
Young GC較爲頻繁。查看服務器的JVM參數如下

-Xms1000M 
-Xmx1800M 
-Xmn350M 
-Xss300K 
-XX:+DisableExplicitGC 
-XX:SurvivorRatio=4 
-XX:+UseParNewGC 
-XX:+UseConcMarkSweepGC 
-XX:CMSInitiatingOccupancyFraction=70 
-XX:+CMSParallelRemarkEnabled 

-Xms表示初始化堆內存

-Xmx表示最大堆內存

-Xmn表示新生代內存

-XX:SurvivorRatio=4表示新生代的Eden是4/10,S1和S2各佔3/10

因此Eden的內存大小爲:0.435010241024字節, 爲14010241024**字節

程序

/**
 * @date : 2020-03-22 09:48
 **/
public class JavaHeapTest {

  public final static int OUTOFMEMORY = 500 * 1024 * 1024;

  private String oom;

  StringBuffer tempOOM = new StringBuffer();

  public JavaHeapTest(int leng) {
    int i = 0;
    while (i < leng) {
      i++;
      try {
        tempOOM.append("a");
      } catch (OutOfMemoryError e) {
        e.printStackTrace();
        break;
      }
    }
    this.oom = tempOOM.toString();
  }

  public String getOom() {
    return oom;
  }

  public static void main(String[] args) {
    for(int i=0;i<50;i++) {
      JavaHeapTest javaHeapTest = new JavaHeapTest(OUTOFMEMORY);
      System.out.println(javaHeapTest.getOom().length());
    }
  }
}

原因

年輕代分爲1個Eden和2個Survivor區(一個是from,另一個是to)。新創建的對象一般都會被分配到Eden區,如果經過第一次GC後仍然存活,就會被移到Survivor區。Survivor區中的對象每經過一次Minor
GC,年齡+1,當年齡增加到一定程度時,會被移動到年老代。

OUTOFMEMORY = 500 * 1024 * 1024,大於Eden內存的大小。新生代分配內存小,導致YoungGC的頻繁觸發。

初始化堆內存沒有和最大堆內存一致,在每次GC後進行內存可能重新分配。

解決方法

提升新生代大小

將初始化堆內存設置爲最大內存

將SurvivorRatio由4修改爲8,讓垃圾在新生代時儘可能的多被回收掉

-Xmn350M -> -Xmn800M
-XX:SurvivorRatio=4 -> -XX:SurvivorRatio=8
-Xms1000m ->-Xms1800m

效果

YoungGC次數明顯減少
在這裏插入圖片描述

對象從出生到回收的全過程

我是一個普通的java對象,我出生在Eden區,在Eden區我還看到和我長的很像的小兄弟,我們在Eden區中玩了挺長時間。有一天Eden區中的人實在是太多了,我就被迫去了Survivor區的“From”區,自從去了Survivor區,我就開始漂了,有時候在Survivor的“From”區,有時候在Survivor的“To”區,居無定所。直到我18歲的時候,爸爸說我成人了,該去社會上闖闖了。於是我就去了年老代那邊,年老代裏,人很多,並且年齡都挺大的,我在這裏也認識了很多人。在年老代裏,我生活了20年(每次GC加一歲),然後被回收。

參考鏈接

https://blog.csdn.net/wy5612087/article/details/52369677/
https://blog.csdn.net/cml_blog/article/details/81057966

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章