1

I have several jvm arguments but have some difficulty understanding them.

  1. the first question is for arguments -Xms20m and -Xss2M (the first one is for heap size and second for thread stack size), does m and M have the same meaning and all means MB?
  2. the second question is, I have the following code snippet, which I expect get a runtime error very quick since the stack size was set to 512M but the code cause my OS to stuck and never give me a runtime error, anyone knows why is that?

Thanks

/**
 *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();
    }
}
Michael.M
  • 21
  • 1
  • 4
  • 1
    Please ask only **one** question per question, you are asking two entirely different things which makes your question too broad. As a short comment: using a stack size of 512 megabytes is absurdly large. Normal values range between a few kilobytes upto a megabyte or so. – Mark Rotteveel Jun 19 '19 at 06:22

2 Answers2

3

1.The first question is for arguments -Xms20m and -Xss2M (the first one is for heap size and second for thread stack size), does m and M have the same meaning and all means MB?

Yes, m and M same meaning and all means MB.

2.The second question is, I have the following code snippet, which I expect get a runtime error very quick since the stack size was set to 512M but the code cause my OS to stuck and never give me a runtime error, anyone knows why is that?

First of all, Java dont used only Heap memory. JVM use non-heap memory in some cases(Call tack, Metaspace etc.). This question answer this situtation. So thread stack use non-heap memory.

Proof:

Run the application XX:NativeMemoryTracking=summary and check used memory with jcmd VM.native_memory command. Related javadoc here.

First, run the application with -XX:NativeMemoryTracking=summary -Xms20m -Xss2M parameters and result:

Native Memory Tracking:

Total: reserved=4581409KB, committed=171605KB

  • Java Heap (reserved=3121152KB, committed=20480KB) (mmap: reserved=3121152KB, committed=20480KB)

  • Thread (reserved=21567KB, committed=21567KB) (thread #16) (stack: reserved=21504KB, committed=21504KB) (malloc=45KB #82) (arena=18KB #27)

And then, run same application with java -XX:NativeMemoryTracking=summary -Xms20m -Xss512M parameters and result:

Native Memory Tracking:

Total: reserved=7714849KB, committed=3305045KB

  • Java Heap (reserved=3121152KB, committed=20480KB) (mmap: reserved=3121152KB, committed=20480KB)

  • Thread (reserved=3155007KB, committed=3155007KB) (thread #16) (stack: reserved=3154944KB, committed=3154944KB) (malloc=45KB #82) (arena=18KB #27)

As you can see, heap memory didn't change in both cases but thread native memory is incresed with last case. Because we increase each stack's size. So application never give a runtime error because stack not use heap memory.

Note: Reserved memory represents the total amount of memory our app can potentially use. Conversely, the committed memory is equal to the amount of memory our app is using right now.

Note 2: For every thread, JVM create one run-time stack which is stored here. Every block of this stack is called activation record/stack frame which store methods calls. All local variables of that method are stored in their corresponding frame. After a thread terminate, it’s run-time stack will be destroyed by JVM. It is not a shared resource.

Turac
  • 667
  • 1
  • 4
  • 19
0

Both m and M mean the same thing.

StackSize is set per thread. So to exceed the 512MB limit, you would need to create a really large local variable. Not something that will be referenced on the heap.

Xss is usually set in the order of a few KB, to account for large stacks, with a bunch of stuff like counters etc in each method on the stack frame. If you want to breach the limit, you are better off writing an infinite recursion where each method allocates a few local variables.

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);
    }
}

In this, each method will store 1 long variable on the stack. If your stack is sufficiently deep, you'll exceed the Xss limit.

Aditya
  • 2,148
  • 3
  • 21
  • 34