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函数的形参数组中
- 虚拟机参数:更改默认配置,用以指导进程运行
JVM参数M配置
堆(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的运行参数有哪些
- 根据异常信息,调整相应的内存参数