JVM默認運行參數
支持JVM運行的重要配置,根據操作系統/物理硬件不同而不同
分爲三類參數:
類型 | 穩定性 | 舉例 |
---|---|---|
- 參數 | 標準參數,比較穩定 | -version |
-X 參數 | 非標準參數,不在所有VM通用 | -Xmx |
-XX 參數 | 非Stable參數,容易變更 | -XX:MaxMetaspaceSize |
下面使用-XX:+PrintFlagsFinal 顯示堆內存的相關參數
C:\Users\Administrator>java -XX:+PrintFlagsFinal -version | findstr HeapSize
uintx ErgoHeapSizeLimit = 0 {product}
uintx HeapSizePerGCThread = 87241520 {product}
uintx InitialHeapSize := 161480704 {product}
uintx LargePageHeapSizeThreshold = 134217728 {product}
uintx MaxHeapSize := 2571108352 {product}
openjdk version "1.8.0_202-release"
OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b03)
OpenJDK 64-Bit Server VM (build 25.202-b03, mixed mode)
可以看到當前JVM初始化堆內存和最大堆內存的大小
更多的參數配置可以到官網查看https://www.oracle.com/java/technologies/javase/vmoptions-jsp.html
下面來演示如何在程序中配置相關參數
程序啓動的兩類參數
- 程序參數:程序需要,存儲在main函數的形參數組中
- 虛擬機參數:更改默認配置,用以指導進程運行
堆(Heap)
- 共享,內存大戶,存儲所有的對象和數組
- -Xms 初始堆值,-Xmx最大堆值
下面代碼設置 VM options 的參數爲: -Xmx5M (見上圖),運行後出現OutOfMemoryError異常
public static void main(String[] args) {
List<User> users = new ArrayList<>();
while (true){
users.add(new User());
System.out.println(users.size());
}
}
輸出:
.
.
.
152694
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.nio.CharBuffer.wrap(CharBuffer.java:373)
JVM 棧(JVM Stack)
- 線程私有,存儲類中每個方法的內容
- -Xss 最大棧值
下面代碼設置 VM options 的參數爲: -Xss1M,運行後出現StackOverflowError異常
public class MyClass {
private int count = 1;
public void sum(){
count ++;
System.out.println(count);
sum();//遞歸調用
}
public static void main(String[] args) {
new MyClass().sum();
}
}
輸出:
.
.
.
10503
Exception in thread "main" java.lang.StackOverflowError
下面代碼設置 VM options 的參數爲: -Xmx5M -Xss1M,運行後出現OutOfMemoryError異常
public class MyClass {
public static void main(String[] args) {
int num = 0;
while (true){
num ++;
System.out.println(num);
new MyThread().start();
}
}
static class MyThread extends Thread{
@Override
public void run() {
long a1,a2,a3,a4,a5,a6,a7,a8,a9,a10;
a1=a2=a3=a4=a5=a6=a7=a8=a9=a10=0;
while (true){
try {
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
}
輸出:
.
.
.
8191
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
方法區(Method Area)
- 存儲類信息、常量池等
- 1.7及以前,永久區(Perm),-XX:PermSize, -XX:MaxPermSize
- 1.8及以後,元數據區,-XX:MetaspaceSize, -XX:MaxMetaspaceSize
C:\Users\Administrator>java -XX:+PrintFlagsFinal -version | findstr Meta
uintx InitialBootClassLoaderMetaspaceSize = 4194304 {product}
uintx MaxMetaspaceExpansion = 5451776 {product}
uintx MaxMetaspaceFreeRatio = 70 {product}
uintx MaxMetaspaceSize = 4294901760 {product}
uintx MetaspaceSize = 21807104 {pd product}
uintx MinMetaspaceExpansion = 339968 {product}
uintx MinMetaspaceFreeRatio = 40 {product}
bool TraceMetadataHumongousAllocation = false {product}
bool UseLargePagesInMetaspace = false {product}
openjdk version "1.8.0_202-release"
OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b03)
OpenJDK 64-Bit Server VM (build 25.202-b03, mixed mode)
說明:
MaxMetaspaceSize:用於設置metaspace區域的最大值。
MetaspaceSize:表示metaspace首次使用不夠而觸發FGC的閾值,只對觸發起作用。
- -XX:MaxMetaspaceSize 最大元數據空間值
下面代碼設置 VM options 的參數爲: -XX:MaxMetaspaceSize=9M,運行後出現OutOfMemoryError異常
public static void generateClass(){
String className = "Hello";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
System.out.println(i);
String realClassName = className + i;
sb.append("class " + realClassName + "{\n");
sb.append("public static void main(String[] args){\n");
sb.append("System.out.print(\"hello world\"); \n");
sb.append("}\n");
sb.append("}");
try {
//使用第三方庫InMemoryJavaCompiler(https://github.com/trung/InMemoryJavaCompiler)
Class<?> helloClass = InMemoryJavaCompiler.newInstance().compile(realClassName, sb.toString());
}catch (Exception e){
e.printStackTrace();
}
}
}
輸出:
0
Exception in thread "main" java.lang.OutOfMemoryError: Compressed class space
總結
- 瞭解JVM的運行參數有哪些
- 根據異常信息,調整相應的內存參數