Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Default -Xss value on Windows for JDK 8

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.

like image 351
Mike Adamenko Avatar asked Jul 17 '17 09:07

Mike Adamenko


People also ask

What is the JDK for Java 8?

The JDK is a development environment for building applications using the Java programming language. The JDK includes tools useful for developing and testing programs written in the Java programming language and running on the JavaTM platform.


2 Answers

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)
like image 50
Ivan Mamontov Avatar answered Nov 15 '22 23:11

Ivan Mamontov


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;
    }
like image 4
yushulx Avatar answered Nov 16 '22 00:11

yushulx