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:
- globals_windows_x86.hpp sets the default values for Windows platform dependent flags used by the runtime system.
- 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)