JVM arguments -Xms and -Xss



我有几个jvm参数,但很难理解它们。

  1. 第一个问题是参数 -Xms20m 和 -Xss2M(第一个是堆大小,第二个是线程堆栈大小),m 和 M 是否具有相同的含义并且都意味着 MB?
  2. 第二个问题是,我有以下代码片段,由于堆栈大小设置为 512M,我希望它很快就会出现运行时错误,但代码导致我的操作系统卡住并且永远不会给我运行时错误,有人知道为什么会这样吗?

谢谢

/**
*VM Args:-Xss512M
*/
public class JavaVMStackOOM{
private void noStop(){
while(true){
}
}
public void stackLeakByThread(){
while(true){
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
noStop();
}
});
thread.start();
}
}
public static void main(String[]args)throws Throwable{
JavaVMStackOOM oom=new JavaVMStackOOM();
oom.stackLeakByThread();
}
}

1.第一个问题是参数 -Xms20m 和 -Xss2M(第一个是堆大小,第二个是线程堆栈大小),m 和 M 是否具有相同的含义并且都意味着 MB?

是的,m和M的含义相同,都意味着MB。

2.第二个问题是,我有以下代码片段,由于堆栈大小设置为 512M,我希望它很快就会出现运行时错误,但代码导致我的操作系统卡住并且永远不会给我运行时错误,有人知道为什么会这样吗?

首先,Java不仅仅使用堆内存。JVM在某些情况下使用非堆内存(调用策略,元空间等)。这个问题回答了这个问题。因此,线程堆栈使用非堆内存。

证明:

运行应用程序XX:NativeMemoryTracking=summary,并使用jcmd VM.native_memory命令检查已用内存。相关的javadoc在这里。

首先,使用 -XX:NativeMemoryTracking=summary -Xms20m -Xss2M参数运行应用程序,结果:

本机内存跟踪:

总计:保留 = 4581409KB,已提交 = 171605KB

  • Java Heap (reserved=3121152KB, committed=20480KB) (mmap: 保留=3121152KB, 提交=20480KB)

  • 线程(保留 = 21567KB
  • ,已提交 = 21567KB) (线程 #16) (堆栈:保留 = 21504KB,已提交 = 21504KB) (malloc=45KB #82) (竞技场=18KB #27)

然后,使用 java 运行相同的应用程序 -XX:NativeMemoryTracking=summary -Xms20m -Xss512M参数和结果:

本机内存跟踪:

总计:保留 = 7714849KB,已提交 = 3305045KB

  • Java Heap (reserved=3121152KB, committed=20480KB) (mmap: 保留=3121152KB, 提交=20480KB)

  • 线程(保留 = 3155007KB
  • ,已提交 = 3155007KB) (线程 #16) (堆栈:保留=3154944KB,提交=3154944KB) (malloc=45KB #82) (竞技场=18KB #27)

如您所见,堆内存在这两种情况下都没有改变,但线程本机内存在最后一种情况下增加。因为我们增加了每个堆栈的大小。因此,应用程序永远不会给出运行时错误,因为堆栈不使用堆内存。

注意:预留内存表示我们的应用可能使用的内存总量。相反,提交的内存等于我们的应用现在使用的内存量。

注意 2:对于每个线程,JVM 创建一个运行时堆栈,该堆栈存储在此处。此堆栈的每个块称为激活记录/堆栈帧,用于存储方法调用。该方法的所有局部变量都存储在其相应的帧中。线程终止后,它的运行时堆栈将被 JVM 销毁。它不是共享资源。

m 和 M 的意思是一样的。

堆栈大小是按线程设置的。因此,要超过 512MB 的限制,您需要创建一个非常大的局部变量。不是将在堆上引用的内容。

Xss 通常以几 KB 的顺序设置,以考虑大型堆栈,在堆栈帧的每个方法中都有一堆东西,如计数器等。 如果你想突破限制,你最好写一个无限递归,其中每个方法分配几个局部变量。

public class JavaVMStackOOM{
public void stackLeakByThread(long i){
stackLeakByThread(i+1);
}
}
public static void main(String[]args)throws Throwable{
JavaVMStackOOM oom=new JavaVMStackOOM();
oom.stackLeakByThread(0l);
}
}

在这种情况下,每个方法将在堆栈上存储 1 个长变量。如果您的堆栈足够深,您将超过 Xss 限制。

最新更新