为什么要减小Java JVM线程堆栈的大小?

我正在阅读一篇关于在Java(以及JBoss平台)中处理Out Of Memory错误情况的文章 ,我看到了这个减少threadstack大小的建议。

如何减少threadstack的大小有助于最大内存错误条件?

当Java创建一个新线程时,它会为该线程的堆栈预先分配一个固定大小的内存块。 通过减小内存块的大小,可以避免内存不足,特别是如果你有很multithreading – 节省内存是减少堆栈大小乘以线程数。

这样做的缺点是您增加了堆栈溢出错误的可能性。

请注意,线程堆栈是在JVM堆之外创建的,因此即使堆中有足够的可用内存,由于内存不足(或用尽地址空间,仍然无法创建线程堆栈) Hawtin正确指出)。

32位JVM存在问题,地址空间可能会耗尽。 减小最大堆栈大小通常不会减少实际分配的内存量。 考虑8k线程,其中256kB保留用于1k的2MB堆栈,即31位地址空间(2GB)。

这个问题几乎随着64位JVM而消失(尽管实际的内存量会增加一点,因为引用的数量是原来的两倍)。 或者,使用非阻塞API可以消除对如此multithreading的需求。

进程中有N个线程,并为每个线程堆栈分配M个字节的内存。 为堆栈使用分配的总内存为N x M.

您可以通过减少线程数(N)或减少为每个线程(M)分配的内存来减少堆栈消耗的总内存。


通常,线程不会使用所有堆栈。 它是预先分配的“以防万一”,稍后将需要它,但如果线程不使用深度调用路径,或者不使用递归,则可能不需要代表它分配的所有堆栈空间。

找到最佳堆栈大小可能是一门艺术。

在尝试更改线程堆栈大小之前,我会尝试其他事情(例如更改幸存者比率或为类定义分配的空间大小)。 很难做到正确,因此很容易得到堆栈溢出错误(这与内存不足错误同样致命。)


经过仔细检查,我从来没有做到这一点。 但话说回来,我可能从未遇到过可以通过更改其线程堆栈大小进行罚款调整的Web应用程序/容器组合。 我有更好的(和非致命的)结果修改幸存者比率。 但那是我的工作经历 。 在不同的工作场所和应用中,YMMV。