Default -Xss value on Windows for JDK 8

12,165

Solution 1

This is not an issue, it is a platform specific behavior with a slight taste of backward compatibility. There are two interesting files in HotSpot's sources:

  1. globals_windows_x86.hpp sets the default values for Windows platform dependent flags used by the runtime system.
  2. os_windows_x86.cpp - creates threads with specified stack size

In globals_windows_x86 HotSpot initializes ThreadStackSize with 0 in order to use system default value:

// Default stack size on Windows is determined by the executable (java.exe
// has a default value of 320K/1MB [32bit/64bit]). Depending on Windows version, changing
// ThreadStackSize to non-zero may have significant impact on memory usage.
// See comments in os_windows.cpp.
define_pd_global(intx, ThreadStackSize,          0); // 0 => use system default
define_pd_global(intx, VMThreadStackSize,        0); // 0 => use system default

In os_windows_x86 there is an explanation why stack size is 0 on Windows platform:

  // Create the Win32 thread
  //
  // Contrary to what MSDN document says, "stack_size" in _beginthreadex()
  // does not specify stack size. Instead, it specifies the size of
  // initially committed space. The stack size is determined by
  // PE header in the executable. If the committed "stack_size" is larger
  // than default value in the PE header, the stack is rounded up to the
  // nearest multiple of 1MB. For example if the launcher has default
  // stack size of 320k, specifying any size less than 320k does not
  // affect the actual stack size at all, it only affects the initial
  // commitment. On the other hand, specifying 'stack_size' larger than
  // default value may cause significant increase in memory usage, because
  // not only the stack space will be rounded up to MB, but also the
  // entire space is committed upfront.
  //
  // Finally Windows XP added a new flag 'STACK_SIZE_PARAM_IS_A_RESERVATION'
  // for CreateThread() that can treat 'stack_size' as stack size. However we
  // are not supposed to call CreateThread() directly according to MSDN
  // document because JVM uses C runtime library. The good news is that the
  // flag appears to work with _beginthredex() as well.

Also you can read a MSDN document.

Why size is zero on Windows platform? This is the simplest way to pass default value to WinAPI and there is an issue in Java main thread http://bugs.java.com/view_bug.do?bug_id=4689767 with resolution:

Windows: the default thread stack size is read from the binary (java.exe); the main thread stack is created with this size.

An alternative solution that hides the differences between the main thread and other threads is to avoid running any java bytecodes in the main thread believe it is not possible in general because of JNI.

It will NOT be fixed on windows till we stop supporting supporting Win95/Win98/WinME

Let me summarize - ThreadStackSize is an internal property and may have any default value, for example 0 on Windows in order to support legacy platforms(ME/98). PrintFlagsFinal is also provides debug information without any guarantee thus it is not correct to refer to this information without certain knowledge. Starting from 1.7.0_45 Hotpot has a nice internal VM feature, called "Native Memory Tracking" (NMT)

java -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics -version

... 
-                    Thread (reserved=14453KB, committed=14453KB)
                            (thread #14)
                            (stack: reserved=14392KB, committed=14392KB)
                            (malloc=44KB #76) 
                            (arena=16KB #28)

You can try to trim the stack size down from the default (which appears to be 1M in this example 14 threads with reserved space 14453 KB) to something less with -Xss256k:

-                    Thread (reserved=10613KB, committed=10613KB)
                            (thread #14)
                            (stack: reserved=10552KB, committed=10552KB)
                            (malloc=44KB #76) 
                            (arena=16KB #28)

Solution 2

I finally found the answer from the JDK source code.

Get the source code:

hg clone http://hg.openjdk.java.net/jdk8/jdk8/hotspot/

According to the JDK documentation, Xss value can change the Java Thread Stack Size. But how does the argument work? Here is the code :

HANDLE thread_handle =
    (HANDLE)_beginthreadex(NULL,
                           (unsigned)stack_size,
                           (unsigned (__stdcall *)(void*)) java_start,
                           thread,
                           CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION,
                           &thread_id);

Xss is assigned to stack_size, which is used to allocate memory for the thread stack.

But what if you set nothing? In os_windows.cpp, see the following paragraph:

// Create the Win32 thread
  //
  // Contrary to what MSDN document says, "stack_size" in _beginthreadex()
  // does not specify stack size. Instead, it specifies the size of
  // initially committed space. The stack size is determined by
  // PE header in the executable. If the committed "stack_size" is larger
  // than default value in the PE header, the stack is rounded up to the
  // nearest multiple of 1MB. For example if the launcher has default
  // stack size of 320k, specifying any size less than 320k does not
  // affect the actual stack size at all, it only affects the initial
  // commitment. On the other hand, specifying 'stack_size' larger than
  // default value may cause significant increase in memory usage, because
  // not only the stack space will be rounded up to MB, but also the
  // entire space is committed upfront.

If you do not set Xss value, the default stack size depends on the PE file(java.exe). If you run a 32-bit Java app, the default stack size is 320K. If you run a 64-bit Java app, the default stack size is 1024K.

We can use following source code to verify the stack size:

    #include <windows.h>
    typedef u_char*       address;

    address os::current_stack_base() {
      MEMORY_BASIC_INFORMATION minfo;
      address stack_bottom;
      size_t stack_size;

      VirtualQuery(&minfo, &minfo, sizeof(minfo));
      stack_bottom =  (address)minfo.AllocationBase;
      stack_size = minfo.RegionSize;

      // Add up the sizes of all the regions with the same
      // AllocationBase.
      while( 1 )
      {
        VirtualQuery(stack_bottom+stack_size, &minfo, sizeof(minfo));
        if ( stack_bottom == (address)minfo.AllocationBase )
          stack_size += minfo.RegionSize;
        else
          break;
      }

    #ifdef _M_IA64
      // IA64 has memory and register stacks
      //
      // This is the stack layout you get on NT/IA64 if you specify 1MB stack limit
      // at thread creation (1MB backing store growing upwards, 1MB memory stack
      // growing downwards, 2MB summed up)
      //
      // ...
      // ------- top of stack (high address) -----
      // |
      // |      1MB
      // |      Backing Store (Register Stack)
      // |
      // |         / \
      // |          |
      // |          |
      // |          |
      // ------------------------ stack base -----
      // |      1MB
      // |      Memory Stack
      // |
      // |          |
      // |          |
      // |          |
      // |         \ /
      // |
      // ----- bottom of stack (low address) -----
      // ...

      stack_size = stack_size / 2;
    #endif
      return stack_bottom + stack_size;
    }
Share:
12,165

Related videos on Youtube

Mike Adamenko
Author by

Mike Adamenko

Answering questions is my way of learning.

Updated on September 16, 2022

Comments

  • Mike Adamenko
    Mike Adamenko over 1 year

    Oracle says that on Windows

    -Xsssize The default value depends on virtual memory

    How i can find out the value of the thread stack size that java allocate on Windows in a given Oracle JVM 8?

    I've tried the solution from where to find default XSS value for Sun/Oracle JVM?

    But it simply prints 0.

    java -XX:+PrintFlagsFinal -version
    

    enter image description here

    java -XX:+PrintFlagsFinal should print actual thread stack size, not 0. Looks like JVM bug for me.

    I want to tune JVM perfomance and want to know how many memory is allocated for the threads' stack. It is specified precisely for unix platforms. And it's weird that i can not get this value for Windows.

  • Mike Adamenko
    Mike Adamenko almost 7 years
    Thanks for response, but it's not answer my question. How can i get actual threadstacksize and why it prints 0 ? In my opinion it should print default value from the OS.
  • Mike Adamenko
    Mike Adamenko almost 7 years
    and if it determined by the java.exe (as said in the HotSpot's sources) , why official doc says that it is depends on virtual memory docs.oracle.com/javase/8/docs/technotes/tools/windows/java.h‌​tml ?
  • Ivan Mamontov
    Ivan Mamontov almost 7 years
    @MikeAdamenko I'he finished my answer. Regarding to your question about official docs - in general any documentation does not cover all specific use cases and contains only common words to ensure freedom of design/development. Also as you can see you did not use the right tool to check the JVM behavior.
  • Mike Adamenko
    Mike Adamenko almost 7 years
    yes, thank you Ivan. I've upvoted ) But actually it could be better to see actual threadstacksize value on PrintFlagsFinal . Looks like bug for me anyway.
  • Holger
    Holger almost 7 years
    “It will NOT be fixed on windows till we stop supporting supporting Win95/Win98/WinME”—how many years ago did this happen?
  • Ivan Mamontov
    Ivan Mamontov almost 7 years
    @Holger yes it is quite old comment and the last version officially supported on Windows 98/Me is 5.0 update 22. However, the code remained unchanged until today.
  • ToFi
    ToFi about 5 years
    > If you run a 32-bit Java app, the default stack size is 320K. If you run a 64-bit Java app, the default stack size is 1024K. < Thanks! That was gold!