当前位置: 首页 > 知识库问答 >
问题:

默认值-Windows for JDK 8上的Xss值

南门魁
2023-03-14

Oracle在Windows上这么说

-xsssize默认值取决于虚拟内存

我如何找出线程堆栈大小的值,java分配在Windows在给定的Oracle JVM 8?

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

但它只是打印0。

java -XX:+PrintFlagsFinal -version

java-XX:PrintFlagsFinal应打印实际的线程堆栈大小,而不是0。对我来说,看起来像是JVM错误。

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


共有2个答案

危卜鹰
2023-03-14

我终于从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;
    }
郑星辰
2023-03-14

这不是问题,这是一种平台特定的行为,有点向后兼容的味道。HotSpot的源代码中有两个有趣的文件:

  1. globals\u windows\u x86。hpp为运行时系统使用的Windows平台相关标志设置默认值

在globals\u windows\u 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\u windows\u 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文档。

为什么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_45Hotpot有一个不错的内部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)

您可以尝试使用Xss256k将堆栈大小从默认值(在本例中为1M,保留空间为14453 KB的14个线程)减少到更小的值:

-                    Thread (reserved=10613KB, committed=10613KB)
                            (thread #14)
                            (stack: reserved=10552KB, committed=10552KB)
                            (malloc=44KB #76) 
                            (arena=16KB #28)
 类似资料:
  • 注:内容翻译自官网文档 Language Guide (proto3) 中的 Default Values 一节 当消息被解析时, 如果被编码的消息没有包含特定的简单元素, 被解析的对象对应的字段被设置为默认值. 默认值是和类型有关的: 对于strings, 默认值是空字符串(注, 是"", 而不是null) 对于bytes, 默认值是空字节(注, 应该是byte[0], 注意这里也不是null)

  • 问题内容: 我感兴趣的selenium超时的默认值,和。因为我想知道,我需要为这些超时设置值吗?或默认值适合selenium webdriver工作。但是我找不到正确的答案,有人说默认值是0,而另一个人说是30秒。 问题答案: 这三个超时由Selenium方程的服务器端管理。您的脚本(使用Java,Python,Ruby,C#或其他任何语言)是将命令发送到位于浏览器中的服务器的客户端。(可能会有中

  • 问题内容: 无法找到文档中的默认值 https://www.elastic.co/guide/zh-CN/elasticsearch/reference/current/query-dsl- minimum-should- match.html 是还是,还是取决于查询是否具有正义或上下文? 问题答案: 默认值取决于查询和上下文: :在查询上下文中且单独存在(否或) :在过滤器上下文中(例如,在查询

  • 主要内容:在创建表时设置默认值约束,在修改表时添加默认值约束,删除默认值约束默认值(Default)的完整称呼是“默认值约束(Default Constraint)”,用来指定某列的默认值。在表中插入一条新记录时,如果没有为某个字段赋值,系统就会自动为这个字段插入默认值。 例如,员工信息表中,部门位置在北京的较多,那么部门位置就可以默认为“北京”,系统就会自动为这个字段赋值为“北京”。 默认值约束通常用在已经设置了非空约束的列,这样能够防止数据表在录入数据时出现错误。 在

  • 我正在开发一个JPA应用程序,并且我正在使用eclipse链接提供程序。 我有一个表T1,其中有一个字段F1定义为非null,并且有一个默认值(“U”)。 我已经定义了一个映射到表T1的实体。该实体有一个映射到字段F1的属性,我已经用注释@ReturnInsert(returnOnly=true)配置了该属性。 文件说明: 使用@返回插入使INSERT操作将值返回到正在写入的对象中 如果在映射到F

  • hibernate有没有一种方法可以为每个字段定义默认值,并且为了数据库大小的缘故,可以写null而不是这些默认值? 对于inst,假设字符串的默认值为“”。我想Hibernate到: 为数据库中具有NULL的每个字段返回". 写NULL到数据库,当我尝试写" 当然,我可以写成千上万个Getters和Setters,但是它能自动完成吗?