在Oracle JVM中,我可以在哪里找到默认的-Xss(堆栈大小)值?

79
有没有人发现过一份列出各个版本Oracle JVM和不同操作系统默认-Xss值的JVM文档?我在jrockit docs中找到了这张表格,但对于使用“普通”Oracle JVM的人来说并不实用。我知道-Xss值会因操作系统(和JVM版本)而异,所以也许没有一份文档列出所有最近的组合。但如果这里的读者知道任何单独的文档,至少列出每个JVM版本(或至少1.6和1.5)的默认-Xss值,甚至只是列出一些操作系统的话,那就是一个好的开始。我特别想知道Windows的默认值。我要补充的是,这很有价值的原因是,我们经常看到人们推荐(错误地认为)可以通过更改-Xss值来解决问题。但如果你不知道你的默认值,那么就无法知道你是否正在通过某人的建议提高或降低该值。他们通常不指明他们使用的版本/操作系统,所以他们的建议是否能帮助你就像赌博一样。比一些文档更好的是,如果有人知道一种查询JVM以获取当前值的方法,无论是通过命令行还是通过API调用,那将更有价值。谢谢。
更新:我已经添加了我自己的答案,总结了各种建议,并指向当前资源(2021年初)来说明答案,包括我在Windows中学到的有关-Xss值的信息。

1
你读过这个吗?http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#threads_oom - Sean
2
谢谢,Sean,但你应该意识到那仅适用于1.4。请注意我已经要求提供任何关于1.5或1.6的参考资料。这些似乎更难找。很抱歉,我应该指出我知道那个1.4技术说明,就像我引用了jrockit 1.5说明一样。 - charlie arehart
6个回答

103

尝试:

java -XX:+PrintFlagsFinal -version | grep ThreadStackSize

14
这看起来很有前途(对于Windows用户,你需要使用“find‘ThreadStackSize’”),但它只是简单地将ThreadStackSize的值报告为0。我不认为这意味着大小为0。虽然有些人可能会说这意味着它正在使用“默认值”,但这只会让我们回到我的问题:在给定的JVM中,默认的XSS值是多少?我无法相信在3.5年内仍无法回答这个问题。我仍然欢迎任何想尝试的人,感谢所有已经尝试的人。 - charlie arehart
谢谢!这是我在64位Linux上得到的结果: java -XX:+PrintFlagsFinal -version | grep ThreadStackSize intx CompilerThreadStackSize = 0 {pd product} intx ThreadStackSize = 1024 {pd product} intx VMThreadStackSize = 1024 {pd product} java版本“1.6.0_24” Java(TM) SE Runtime Environment(build 1.6.0_24-b07) - Scot
2
@Rohit,大小以千字节为单位存储:https://bugs.openjdk.java.net/browse/JDK-8145458 - Julien
3
差不多晚了五年... 使用 java -XX:+PrintFlagsFinal -version 显示 ThreadStackSize 应该是 1024k,但实际上它似乎是 64Mb,如 /proc/<pid>/maps 所示。而且,将 -Xss 改为 4Mb(例如, java -Xss4m)并比较 /proc/<pid>/maps 确认了“某些东西”,我假设这是线程堆栈分配,从 64Mb 减少到 4Mb。 我使用了这个小工具来显示内存段大小:https://gist.github.com/cosimo/e90a9f6daa1fbdc62a89843cf27f005a 最后,要显示正在运行的进程的 JVM 标志,请使用 jcmd <pid> VM.flags - Cosimo
1
Cosimo,你是在指没有指定 XSS 时的 Windows 吗? 我发现 jcmd 报告为0,至少对于其报告的 VMThreadStackSize、ThreadStackSize 和 CompilerThreadStackSize,假设 XSS 与它们中的任何一个直接相关。 这类似于我之前报告的 printflagsfinal 在此情况下也报告为0。 所以遗憾的是,如果没有设置,这些都不是了解 Windows 上“当前” XSS 的方法。 - charlie arehart

25

这些信息现在出现在Oracle Hotspot FAQ中。http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#threads_oom

您可能遇到了线程默认堆栈大小的问题。在Java SE 6中,Sparc上32位VM的默认值为512k,在64位VM中为1024k。在x86 Solaris/Linux上,32位VM中的默认值是320k,在64位VM中是1024k。

在Windows上,默认的线程堆栈大小从二进制文件(java.exe)中读取。截至Java SE 6,32位VM中该值为320k,在64位VM中为1024k。

您可以通过使用-Xss选项来减少堆栈大小。例如:

java -server -Xss64k

请注意,在某些版本的Windows上,操作系统可能会使用非常粗略的粒度来四舍五入线程堆栈大小。如果请求的大小比默认大小少1K或更多,则堆栈大小将四舍五入为默认大小;否则,堆栈大小将四舍五入为1 MB的倍数。

64k是每个线程允许的最小堆栈空间。


2
谢谢,本。这是迄今为止最直接的潜在答案,但有一个小问题:该技术说明似乎是针对旧版本的Java(“1.4”和“SE 5.0”和“SE 6”)。很可能这些信息对于Java 7或8已经不再准确。对于那些感兴趣的人来说,应该注意这一点。但现在看起来似乎确认了在Windows中,唯一真正的方法是查看源代码。好吧。(至少他们说了它是用于Java 6的32/64位Windows!) - charlie arehart
仍在寻找任何方法来获取jvm报告当前堆栈大小。无法相信这么难以获得,尤其是考虑到即使只是找到默认值也需要做出上述努力。有些人可能会提出jmx,但我已经搜索了Java API文档,但没有发现。有些人可能会建议使用类似于“java-XX:+PrintFlagsFinal | find“Stack””的东西,但它只报告在启动JVM时指定XX参数时指定的任何值(如果有)。它不报告留给其默认值的值。 - charlie arehart

14
这个问题的答案已经让人历经波折,起初在2011年被提出来,多年来得到了各种各样的回答。一些人建议使用-XX:+PrintFlagsFinal JVM参数,这可能对大多数情况最为适用,但在Windows系统上并没有什么帮助(总是报告为0)。还有一些人分享了各种资源(针对不同的JVM和版本),其中有一些尝试回答了这个问题,但通常没有解释清楚,或者没有解释给那些在Windows上运行Oracle JVM的人听。
至少有一点更加清楚了:随着Java 11成为目前(2021年)最新的Oracle JVM长期支持版本,我发现了一份针对该版本的文档,列出了不同操作系统下XSS(也称为ThreadStackSize)的默认值。该文档位于https://docs.oracle.com/en/java/javase/11/tools/java.html#GUID-3B1CE181-CD30-4178-9602-230B800D4FAE。以下是它所报告的内容(以防链接在未来失效):
  • Linux/x64 (64-bit): 1024 KB
  • macOS (64-bit): 1024 KB
  • Oracle Solaris/x64 (64-bit): 1024 KB
  • Windows: 默认值取决于虚拟内存
遗憾的是,Windows用户仍然会想知道:“depends on virtual memory”是什么意思?我想它当然是指Windows本身的虚拟内存,但即便如此,我们如何将其转化为我们应该期望jvm线程实际堆栈大小的值呢?
回到我的最初问题:我想知道默认值是多少,因为经常有人建议通过更改" -XSS " jvm参数(为他们提出的某个值)来解决某些问题。但我们怎么知道我们是否比默认值更大或更小呢?根据所解决的问题,了解这一点可能非常重要!
10年后,我想这是一个可能无法得出结论的神话探索。但谁知道呢,也许现在或未来的某个人可以提供新信息。或者Java 17(预计下一个LTS版本)可能会改变事情。(明确的是,在我写作时,Java 13或以上版本都没有该页面的版本。)
如果没有其他的,我把这个问题留给后人,至少帮助其他面临这个问题的人知道他们不是疯了,因为很难得到直接的答案(特别是关于Windows的默认 XSS 值以及更改它是否会相对于默认值提高或降低大小)。

有人指向我另一个SO线程,其中有人断言(通过分析JAva 8的JDK源代码)他们发现64位Windows中默认值为1m(1024k)。更多信息请参见:https://dev59.com/H6Pia4cB1Zd3GeqPzX0s#52869631。如果我进行更多测试以确认或否认该断言(尽管有代码),我将报告,或者我很乐意听到其他人的意见。但这比Oracle的“取决于”答案更好。 :-) - charlie arehart

6
您可以在Oracle网站上找到它,该选项位于“-XX:ThreadStackSize”下面,意思与“-Xss”相同。请参考这里

谢谢。我确实发现其他人断言并证明 XSS 和 ThreadStackSize 看起来是相同的东西,只是在 JVM 的演化历程中来自于不同时代的名称。 - charlie arehart
关于该页面提到的默认值,这个问题比较难懂。是的,左栏中列出了“-XX:ThreadStackSize=512”,其标题指示该列显示“选项和默认值”,但右栏却写着“线程堆栈大小(以K字节为单位)。 (0表示使用默认堆栈大小)[Sparc:512;Solaris x86:320(在5.0及更早版本中为256);Sparc 64位:1024;Linux amd64:1024(在5.0及更早版本中为0);其他所有操作系统都为0。]”我主要关注Windows,但不知道第一句话中的“其他所有操作系统都为0”是什么意思,因为它说“0表示使用默认堆栈大小”。 :( - charlie arehart
根据左列及其标题,512是默认值。因此512适用于Windows。 - keypress
按键,不,那不是这样的。512确实在该页面的左列中列为“默认值”,但该页面没有任何关于显示Windows默认值的内容。因此,threadstacksize框确实显示了除Windows之外的其他内容。而且,Windows将被归类为“所有其他操作系统”,显示为“0”,正如在此处讨论的其他地方所述,这意味着“任何操作系统默认值”,这再次告诉我们什么都没有。 - charlie arehart
顺便提一下,那个页面(keypress分享的)确实在顶部有一个关于Windows Java 8文档的链接(https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html),并且该页面至少对xss说了这个:“默认值取决于虚拟内存。”再次强调,这并不是很有帮助,但至少是一种尝试。这与其他讨论(其他答案和评论)相反,在那里一些人指出Java源代码将指示默认大小。我将提供一个新答案,指向一个Java 11资源,稍微深入一点(只是一点)。 - charlie arehart

3

对于热点(hotspot),这取决于你的架构和其他因素。

默认的堆栈大小可以在源代码中找到,它位于与特定平台相关的头文件中,例如:

谷歌代码搜索 (注:此服务自回答时已停用)更新:Nebelmann提供了一个新链接:Openjdk源码:globals_windows_x86.hpp

不确定是否有帮助,但这是一个开始。


对于 OpenJDK 7,文件下载链接如下:http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/473cce303f13/src/os_cpu/windows_x86/vm/globals_windows_x86.hpp - Bastien Jansen
有趣的是,Greg和Inger。我猜有些人可能想要探索他们的Java源代码来找到它,但由于许多人在没有源代码的情况下部署JDK或JRE,这对他们没有帮助(除非他们再次获取它,或者像你分享的资源一样找到源代码并希望在那里找到适合他们特定环境的源代码)。是的,Greg,我从一开始就承认这确实是与环境相关的。还是感谢你们两个提供的建议。 - charlie arehart

2

IBM Java 6用户指南提供了默认设置(来源):

Xss <size> 适用于Java Threads 32位:

AIX®: 256KB
IBM®I: 256KB
Linux: 256KB
Windows: 256KB
z/OS®: 256KB

4
谢谢,chepseskaf,但是我在标题和正文中再次询问的是关于Oracle/Sun JVM的问题。你提供的资源实际上是来自IBM JVM,这不同于Oracle/Sun JVM。因此,虽然信息很有趣,但我们不能得出它同样适用于Oracle/Sun JVM的结论。 - charlie arehart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接