Windows上JDK 8的默认-Xss值

Mik*_*nko 5 java jvm jvm-hotspot

甲骨文表示在Windows上

-Xsssize缺省值取决于虚拟内存

如何在给定的Oracle JVM 8中找出Java在Windows上分配的线程堆栈大小的值?

我已尝试从哪里找到Sun / Oracle JVM的默认XSS值的解决方案

但它只打印0。

java -XX:+PrintFlagsFinal -version
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

java -XX:+PrintFlagsFinal 应该打印实际的线程堆栈大小,而不是0。对我来说似乎是JVM bug。

我想调整JVM性能,并想知道为线程的堆栈分配了多少内存。它是为unix平台专门指定的。我无法为Windows获得此值,这很奇怪。

Iva*_*tov 6

这不是问题,它是特定于平台的行为,带有一点向后兼容性。HotSpot的来源中有两个有趣的文件:

  1. globals_windows_x86.hpp设置运行时系统使用的Windows平台相关标志的默认值。
  2. os_windows_x86.cpp-创建具有指定堆栈大小的线程

在globals_windows_x86中,HotSpot使用0初始化ThreadStackSize以便使用系统默认值:

// 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
Run Code Online (Sandbox Code Playgroud)

在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.
Run Code Online (Sandbox Code Playgroud)

您也可以阅读MSDN文档

为什么在Windows平台上大小为零?这是将默认值传递给WinAPI的最简单方法,并且Java主线程http://bugs.java.com/view_bug.do?bug_id=4689767中存在一个问题,分辨率为:

Windows:默认线程堆栈大小是从二进制文件(java.exe)中读取的;主线程堆栈将以此大小创建。

隐藏主线程和其他线程之间差异的另一种解决方案是避免在主线程中运行任何Java字节码,因为这通常由于JNI是不可能的。

在我们停止支持Win95 / Win98 / WinME之前,它不会在Windows上修复。

让我总结一下- ThreadStackSize是一个内部属性,可以具有任何默认值,例如在Windows上为0以支持旧版平台(ME / 98)。PrintFlagsFinal它还提供了调试信息而没有任何保证,因此在没有某些知识的情况下引用此信息是不正确的。从1.7.0_45开始,Hotpot具有不错的内部VM功能,称为“本机内存跟踪”(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)
Run Code Online (Sandbox Code Playgroud)

您可以尝试将堆栈大小从默认值(在此示例中为14个线程,保留空间14453 KB)减小为默认值,以减小-Xss256k

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


yus*_*ulx 5

终于从JDK源码中找到了答案。

获取源代码:

hg clone http://hg.openjdk.java.net/jdk8/jdk8/hotspot/
Run Code Online (Sandbox Code Playgroud)

根据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);
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)

如果不设置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;
    }
Run Code Online (Sandbox Code Playgroud)

  • &gt; 如果运行 32 位 Java 应用程序,则默认堆栈大小为 320K。如果运行 64 位 Java 应用程序,则默认堆栈大小为 1024K。&lt;谢谢!那是金子! (5认同)