我正在阅读article处理Java(以及JBoss平台)中的Out Of Memory错误情况,我看到了这个减少threadstack大小的建议。
如何减少threadstack的大小有助于最大内存错误条件?
答案 0 :(得分:9)
当Java创建一个新线程时,它会为该线程的堆栈预先分配一个固定大小的内存块。通过减小内存块的大小,可以避免内存不足,特别是如果你有很多线程 - 节省内存是减少堆栈大小乘以线程数。
这样做的缺点是您增加了堆栈溢出错误的可能性。
请注意,线程堆栈是在JVM堆之外创建的,因此即使堆中有足够的可用内存,由于内存不足(或者地址空间不足),仍然可能无法创建线程堆栈正如Tom Hawtin正确指出的那样)。
答案 1 :(得分:4)
32位JVM存在问题,地址空间可能会耗尽。减小最大堆栈大小通常不会减少实际分配的内存量。考虑8k线程,其中256kB保留用于1k的2MB堆栈,那是31位的地址空间(2GB)。
问题几乎随着64位JVM而消失(尽管实际的内存量会增加一点,因为引用的数量是原来的两倍)。或者,使用非阻塞API可以消除对非常多线程的需求。
答案 2 :(得分:2)
进程中有N个线程,并为每个线程堆栈分配M个字节的内存。为堆栈使用分配的总内存为N x M.
您可以通过减少线程数(N)或减少为每个线程(M)分配的内存来减少堆栈消耗的总内存。
线程通常不会使用所有堆栈。它是预分配的“以防万一”以后需要它,但如果线程不使用深度调用路径,或者不使用递归,则可能不需要代表它分配的所有堆栈空间。
找到最佳堆栈大小可能是一门艺术。
答案 3 :(得分:2)
在尝试更改线程堆栈大小之前,我会尝试其他事情(例如更改幸存者比率或为类定义分配的空间大小)。很难做到正确,因此很容易出现堆栈溢出错误(这与内存不足错误同样致命。)
即使经过仔细检查,我也从来没有这样做过。但话说回来,我可能从未遇到过可以通过更改其线程堆栈大小来细化的Web应用程序/容器组合。我有更好的(和非致命的)结果修改幸存者比率。但那已经 我的工作经验 。在不同的工作场所和应用中,YMMV。