Windows 上的默认 -Xss 值 JDK 8
Default -Xss value on Windows for JDK 8
-Xsssize The default value depends on virtual memory
如何找出给定 Oracle JVM 8 中 java 在 Windows 上分配的线程堆栈大小的值?
我试过 where to find default XSS value for Sun/Oracle JVM?
的解决方案
但它只是打印 0。
java -XX:+PrintFlagsFinal -version
java -XX:+PrintFlagsFinal
应该打印实际的线程堆栈大小,而不是 0。对我来说看起来像 JVM 错误。
我想调整 JVM 性能并想知道为线程堆栈分配了多少内存。它是为 unix platforms 精确指定的。奇怪的是我无法获得 Windows.
的这个值
这不是问题,它是一个平台特定的行为,带有轻微的向后兼容性。 HotSpot 的源代码中有两个有趣的文件:
- globals_windows_x86.hpp 设置运行时系统使用的 Windows 平台相关标志的默认值。
- os_windows_x86.cpp - 创建具有指定堆栈大小的线程
在 globals_windows_x86 中,HotSpot 将 ThreadStackSize 初始化为 0 以使用系统默认值:
// 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
在 os_windows_x86 中有一个解释,为什么在 Windows 平台上堆栈大小为 0:
// 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.
您还可以阅读 MSDN document。
为什么 Windows 平台上的大小为零?这是将默认值传递给 WinAPI 的最简单方法,Java 主线程 http://bugs.java.com/view_bug.do?bug_id=4689767 中存在问题,分辨率为:
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
让我总结一下 - ThreadStackSize
是一个内部 属性 并且可以有任何默认值,例如 Windows 上的 0 以支持旧平台(ME/98 ). PrintFlagsFinal
也提供调试信息,没有任何保证,因此在没有一定知识的情况下引用此信息是不正确的。从 1.7.0_45 开始,Hotpot 有一个很好的内部 VM 功能,称为 "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)
您可以尝试 trim 将堆栈大小从默认值(在本例中显示为 1M,保留 space 14453 KB)减少到 -Xss256k
:
- Thread (reserved=10613KB, committed=10613KB)
(thread #14)
(stack: reserved=10552KB, committed=10552KB)
(malloc=44KB #76)
(arena=16KB #28)
我终于从JDK源代码中找到了答案。
获取源代码:
hg clone http://hg.openjdk.java.net/jdk8/jdk8/hotspot/
根据 JDK 文档,Xss 值可以更改 Java 线程堆栈大小 。但是这个论点是如何运作的呢?这是代码:
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赋值给stack_size,用于为线程栈分配内存
但是如果什么都不设置呢?在os_windows.cpp中,见以下段落:
// 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.
如果不设置Xss值,默认堆栈大小取决于PE文件(java.exe)。如果您 运行 32 位 Java 应用程序,则默认堆栈大小为 320K。如果您 运行 64 位 Java 应用程序,则默认堆栈大小为 1024K.
我们可以使用以下源代码来验证堆栈大小:
#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;
}
-Xsssize The default value depends on virtual memory
如何找出给定 Oracle JVM 8 中 java 在 Windows 上分配的线程堆栈大小的值?
我试过 where to find default XSS value for Sun/Oracle JVM?
的解决方案但它只是打印 0。
java -XX:+PrintFlagsFinal -version
java -XX:+PrintFlagsFinal
应该打印实际的线程堆栈大小,而不是 0。对我来说看起来像 JVM 错误。
我想调整 JVM 性能并想知道为线程堆栈分配了多少内存。它是为 unix platforms 精确指定的。奇怪的是我无法获得 Windows.
的这个值这不是问题,它是一个平台特定的行为,带有轻微的向后兼容性。 HotSpot 的源代码中有两个有趣的文件:
- globals_windows_x86.hpp 设置运行时系统使用的 Windows 平台相关标志的默认值。
- os_windows_x86.cpp - 创建具有指定堆栈大小的线程
在 globals_windows_x86 中,HotSpot 将 ThreadStackSize 初始化为 0 以使用系统默认值:
// 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
在 os_windows_x86 中有一个解释,为什么在 Windows 平台上堆栈大小为 0:
// 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.
您还可以阅读 MSDN document。
为什么 Windows 平台上的大小为零?这是将默认值传递给 WinAPI 的最简单方法,Java 主线程 http://bugs.java.com/view_bug.do?bug_id=4689767 中存在问题,分辨率为:
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
让我总结一下 - ThreadStackSize
是一个内部 属性 并且可以有任何默认值,例如 Windows 上的 0 以支持旧平台(ME/98 ). PrintFlagsFinal
也提供调试信息,没有任何保证,因此在没有一定知识的情况下引用此信息是不正确的。从 1.7.0_45 开始,Hotpot 有一个很好的内部 VM 功能,称为 "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)
您可以尝试 trim 将堆栈大小从默认值(在本例中显示为 1M,保留 space 14453 KB)减少到 -Xss256k
:
- Thread (reserved=10613KB, committed=10613KB)
(thread #14)
(stack: reserved=10552KB, committed=10552KB)
(malloc=44KB #76)
(arena=16KB #28)
我终于从JDK源代码中找到了答案。
获取源代码:
hg clone http://hg.openjdk.java.net/jdk8/jdk8/hotspot/
根据 JDK 文档,Xss 值可以更改 Java 线程堆栈大小 。但是这个论点是如何运作的呢?这是代码:
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赋值给stack_size,用于为线程栈分配内存
但是如果什么都不设置呢?在os_windows.cpp中,见以下段落:
// 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.
如果不设置Xss值,默认堆栈大小取决于PE文件(java.exe)。如果您 运行 32 位 Java 应用程序,则默认堆栈大小为 320K。如果您 运行 64 位 Java 应用程序,则默认堆栈大小为 1024K.
我们可以使用以下源代码来验证堆栈大小:
#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;
}