2010-04-12 112 views

回答

9

當Java創建一個新線程時,它爲該線程的堆棧預分配一個固定大小的內存塊。通過減少內存塊的大小,可以避免內存不足,尤其是在有很多線程的情況下 - 內存節省是堆棧大小減少了線程數量。

這樣做的缺點是你增加了堆棧溢出錯誤的可能性。

請注意,線程堆棧是在JVM堆外部創建的,因此即使堆中有足夠的可用內存,由於內存不足(或地址不足)仍可能無法創建線程堆棧空間,正如湯姆霍金正確指出的那樣)。

+0

好的,我將跟蹤VirtualVm並嘗試確定堆棧空間是否需要更改。我的猜測是它不會。 – djangofan 2010-04-13 15:43:21

2

進程中有N個線程,並且爲每個線程堆棧分配了M字節的內存。分配給堆棧使用的總內存爲N x M。

通過減少線程數(N)或減少爲每個線程(M)分配的內存,可以減少堆棧佔用的內存總量。


通常一個線程不會使用所有的堆棧。它是預先分配的,以備後用,但如果線程不使用深呼叫路徑或不使用遞歸,則可能不需要爲其分配所有的堆棧空間。

尋找最佳堆棧大小可能是一門藝術。

4

問題存在於32位JVM上,地址空間可能會耗盡。減小最大堆棧大小通常不會減少實際分配的內存量。考慮8k線程,256kB爲2k的1k堆棧保留,這是31比特的地址空間(2GB)。

這個問題幾乎消失在64位JVM中(雖然實際的內存量會增加一點,因爲引用是兩倍大)。或者,使用非阻塞的API可以消除對這麼多線程的需求。

+1

Hotspot 6u14中引入的壓縮對象指針有助於緩解這種情況。 HTTP://wikis.sun。COM /顯示/ HotSpotInternals/CompressedOops – 2011-11-30 15:33:25

2

在嘗試更改線程堆棧大小之前,我會嘗試其他事情(例如更改倖存者比率或爲類定義分配的空間大小)。這是很難得到它的權利,因此很容易得到一個堆棧溢出錯誤(這是作爲一個內存不足的錯誤同樣是致命的。)


即使經過仔細檢查我從來沒有得到這一權利。但是再一次,我可能從來沒有遇到過一個web應用程序/容器組合,可以通過更改其線程堆棧大小來進行微調。我有更好的(和非致命的)結果修改倖存者比率。但那已經是我的工作經驗。在不同的工作場所和應用中,YMMV。