3、JVM 調優 - 堆

1、Java堆結構與配置參數

(1)Java7堆內存結構圖

 

(2) Java8堆內存結構圖

 

2.2 堆內存調優簡介

(1)調優參數:

 

(2)如何查看堆內存信息

public static void main(String[] args) {

// 返回 Java 虛擬機試圖使用的最大內存量。

long maxMemory = Runtime.getRuntime().maxMemory() ;

// 返回 Java 虛擬機中的內存總量。

long totalMemory = Runtime.getRuntime().totalMemory() ;

System.out.println("MAX_MEMORY = " + maxMemory + "(字節)、"

+ (maxMemory / (double)1024 / 1024) + "MB");

System.out.println("TOTAL_MEMORY = " + totalMemory + "(字節)、"

+ (totalMemory / (double)1024 / 1024) + "MB");

}

(3)設置堆內存參數

在 VM arguments中設置: -Xms1024m -Xmx1024m -XX:+PrintGCDetails

(4)堆空間溢出

在 VM arguments中設置: -Xms8m -Xmx8m -XX:+PrintGCDetails

public class Oom {

public static void main(String[] args) {

String str = "";

while (true){

str += str + "OutOfMemoryError"; //在堆中不停的實例化對象

System.out.println(str);

}

}

}

總結:

1)新生區總結

  1. 新生區是類的誕生、成長、消亡的區域,一個類在這裏產生,應用,最後被垃圾回收器收集,結束生命。
  2. 新生區又分爲兩部分: 伊甸區(Eden space)和倖存者區(Survivor pace) ,所有的類都是在伊甸區被new出來的。
  3. 倖存區有兩個: 0區(Survivor 0 space)和1區(Survivor 1 space)。當伊甸園的空間用完時,程序又需要創建對象,JVM的垃圾回收器將對伊甸園區進行垃圾回收(Minor GC),將伊甸園區中的不再被其他對象所引用的對象進行銷燬。然後將伊甸園中的剩餘對象移動到倖存 0區。若倖存 0區也滿了,再對該區進行垃圾回收,然後移動到 1 區。那如果1 區也滿了呢?再移動到養老區。若養老區也滿了,那麼這個時候將產生MajorGC(FullGC),進行養老區的內存清理。
  4. 若養老區執行了Full GC之後發現依然無法進行對象的保存,就會產生OOM異常“OutOfMemoryError”。如果出現java.lang.OutOfMemoryError: Java heap space異常,說明Java虛擬機的堆內存不夠。原因有二:
  • Java虛擬機的堆內存設置不夠,可以通過參數-Xms、-Xmx來調整。
  • 代碼中創建了大量大對象,並且長時間不能被垃圾收集器收集(存在被引用)。

2)永久帶總結

  1. 永久存儲區是一個常駐內存區域,用於存放JDK自身所攜帶的 Class,Interface 的元數據,也就是說它存儲的是運行環境必須的類信息,被裝載進此區域的數據是不會被垃圾回收器回收掉的,關閉 JVM 纔會釋放此區域所佔用的內存。
  2. 如果出現java.lang.OutOfMemoryError: PermGen space,說明是Java虛擬機對永久代Perm內存設置不夠。一般出現這種情況,都是程序啓動需要加載大量的第三方jar包。例如:在一個Tomcat下部署了太多的應用。或者大量動態反射生成的類不斷被加載,最終導致Perm區被佔滿。

3)方法區和堆總結

  1. 實際而言,方法區(Method Area)和堆一樣,是各個線程共享的內存區域,它用於存儲虛擬機加載的:類信息+普通常量+靜態常量+編譯器編譯後的代碼等等,雖然JVM規範將方法區描述爲堆的一個邏輯部分,但它卻還有一個別名叫做Non-Heap(非堆),目的就是要和堆分開。
  2. 對於HotSpot虛擬機,很多開發者習慣將方法區稱之爲“永久代(Parmanent Gen)” ,但嚴格本質上說兩者不同,或者說使用永久代來實現方法區而已,永久代是方法區(相當於是一個接口interface)的一個實現,jdk1.8的版本中,已經將原本放在永久代的字符串常量池移走。

補充:RUNTIME CONSTANT POOL,運行時常量池

常量池(Constant Pool)是方法區的一部分,Class文件除了有類的版本、字段、方法、接口等描述信息外,還有一項信息就是常量池,常量池用於存放編譯期間生成的各種字面量和符號引用,這部分內容將在類加載後進入方法區的運行時常量池中存放。

 

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