先貼上一段參數設置html
JAVA_OPTS=" $JAVA_OPTS -Dspring.profiles.active=test -DLOG_DIR=/home/work/logs
-Xms2048m -Xmx2048m -Xss1m -XX:NewSize=512m -XX:MaxNewSize=512m -XX:PermSize=128m
-XX:MaxPermSize=512m -XX:SurvivorRatio=6 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -Dfile.encoding=UTF-8"
不少時候,將代碼部署到服務器,都會對JAVA_OPTS進行一些操做,大多數狀況對主要兩個知道是幹嗎的,其實的哪copy的算哪的。java
因此,看了點資料,想寫點東西。spring
Java虛擬機運行時數據區,主要包括如下部分:方法區、堆,它們是線程共用的部分;虛擬機棧、本地方法棧、程序計數器。下面我服務器
大概講講如上幾個部分。spa
1. 程序計數器。 線程本身的數據區,用以記錄當前線程所執行的字節碼的行號指示器,主要用於在線程切換過程當中,保證切換後可以恢復到正確的執行位置,此區域是唯一一個在Java虛擬機規範中沒有規定任何OOM狀況的區域。 2. Java虛擬機棧。 線程獨自擁有,生命週期與線程相同。異常情況,若線程請求棧深度大於虛擬機所容許,則StackOverflowError,若虛擬機棧可動態擴展,在擴展沒法申請獲得足夠內存則OOM。 3. 本地方法棧。 相對於虛擬機棧爲虛擬機執行Java方法服務,本地方法棧則爲虛擬機使到的Native方法服務。爲線程私有空間。 4. Java堆。 線程共享區域,在虛擬機啓動時建立,爲GC管理的主要區域。可設置爲固定或者可擴展大小,由-Xmx和-Xms控制,設置成同樣即爲固定。若無空間分配實例,且沒法擴展,則OOM。 5. 方法區。 線程共享,用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等。此區域也要GC,主要是對常量池回收和對類型的卸載,會有OOM異常。(運行時常量池,用於存放編譯期生成的各類字面量和符號引用,在類加載後存儲,運行期間也可能將新的常量放入池中,如String類的intern()方法)。
來幾個簡單實例。線程
Java堆溢出:code
package com.wdm.mem; import java.util.ArrayList; import java.util.List; /* * VM: -Xms1m -Xmx1m -XX:+HeapDumpOnOutOfMemoryError */ public class HeapOOM { static class OOMObejct { } public static void main(String[] args) { List<OOMObejct> list = new ArrayList<>(); System.out.println("start"); int i = 0; while (true) { i++; if (i % 10000 == 0) { System.out.println(i); } list.add(new OOMObejct()); } } }
輸出以下:htm
start 10000 20000 30000 40000 java.lang.OutOfMemoryError: Java heap space Dumping heap to java_pid21966.hprof ... Heap dump file created [2399791 bytes in 0.014 secs] Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Arrays.java:3210) at java.util.Arrays.copyOf(Arrays.java:3181) at java.util.ArrayList.grow(ArrayList.java:261) at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235) at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227) at java.util.ArrayList.add(ArrayList.java:458) at com.wdm.mem.HeapOOM.main(HeapOOM.java:23)
虛擬機棧和本地方法棧溢出:blog
package com.wdm.mem; /* * VM: -Xss160k */ public class JavaVMStackSOF { private int stackLen = 1; public void stackLeak() { stackLen++; stackLeak(); } public static void main(String[] args) throws Throwable { JavaVMStackSOF oom = new JavaVMStackSOF(); try { oom.stackLeak(); } catch (Throwable e) { System.out.println("stack length:" + oom.stackLen); throw e; } } } // 輸出:
stack length:771Exception in thread "main" java.lang.StackOverflowError at com.wdm.mem.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:11) at com.wdm.mem.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:12) at com.wdm.mem.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:12) at com.wdm.mem.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:12) // 設置小於160k時報錯 The stack size specified is too small, Specify at least 160k Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Program will exit.
運行時常量池溢出:生命週期
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=1M; support was removed in 8.0 Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=1M; support was removed in 8.0 package com.wdm.mem; import java.util.List; import java.util.ArrayList; /* * VM: -XX:PermSize=10M -XX:MaxPermSize=10M */ public class RuntimeConsPoolOOM { public static void main(String[] args) { List<String> list = new ArrayList<>(); int i = 0; while (true) { list.add(String.valueOf(i++).intern()); } } } JDK8已經不用這兩個參數了:能夠看這個http://www.cnblogs.com/paddix/p/5309550.html
PS:此文由看《深刻理解Java虛擬機:JVM高級特性與最佳實踐》而來