与Java 7相比,运行相同递归代码的相同线程似乎在Java 8中消耗更多堆栈内存

San*_*hat 3 memory stack-overflow recursion jvm-hotspot java-8

我在"stackoverflow"网站上问一个关于"java堆栈溢出"的问题:)

对于特定输入进行一些递归函数调用的特定线程在Oracle Java 7(64位)中运行良好,配置的堆栈大小为228k(-Xss228k).

但是,为同一输入运行相同递归代码的同一线程会抛出Oracle Java 8(64位)中的java.lang.StackOverflowError,其堆栈大小为228k.如果堆栈大小增加到512k(-Xss512k),它在Java 8中运行良好.

知道为什么会这样吗?与Java 7相比,在Java 8(Hotspot JVM)中是否进行了任何更改,这可能会增加递归函数调用的堆栈内存消耗?如果需要,我可以提供更多细节.

(编辑)注意:相同的递归深度在Java 7中"始终"起作用,但在Java 8中"始终"失败,堆栈大小为228k.

Tag*_*eev 5

我为不同的递归场景(静态或实例方法,不同数量的int参数)编写了一个小测试.这是StackOverflowError不同版本的HotSpot JVM 64bit with -Xss228koption 的结果(发生之前的调用次数).请注意,运行之间的数字有所不同(我为每个JVM启动了两次):

          St/0  St/1  St/2  St/3  St/4  In/0  In/1  In/2  In/3  In/4
1.7.0_60  2720  2519  2309  2131  1979  2519  2309  2131  1979  1847
1.7.0_60  2716  2516  2306  2128  1976  2516  2306  2128  1976  1845
1.7.0_79  2716  2516  2306  2128  1976  2516  2306  2128  1976  1845
1.7.0_79  2729  2528  2317  2139  1986  2528  2317  2139  1986  1853
1.7.0_80  2718  2518  2308  2130  1978  2518  2308  2130  1978  1846
1.7.0_80  2738  2536  2324  2146  1992  2536  2324  2146  1992  1859
____________________________________________________________________
1.8.0_25  2818  2469  2263  2089  1940  2469  2263  2089  1940  1810
1.8.0_25  3279  2468  2262  2088  1939  2468  2262  2088  1939  1810
1.8.0_40  2714  2467  2262  2088  1938  2467  2262  2088  1938  1809
1.8.0_40  2735  2486  2279  2104  1953  2486  2279  2104  1953  1823
1.8.0_60  2729  2481  2274  2099  1949  2481  2274  2099  1949  1819
1.8.0_60  2719  2472  2266  2091  1942  2472  2266  2091  1942  1812
____________________________________________________________________
1.9_b80   2717  2470  2264  2090  1941  2470  2264  2090  1941  1811
1.9_b80   2715  2468  2263  2088  1939  2468  2263  2088  1939  1810
Run Code Online (Sandbox Code Playgroud)

由于实例调用需要作为附加参数传递,因此非常期望与之Instance/0相同.Static/1this

事实上,在Static/0JDK 7和JDK 8之间允许的递归调用数量有所降低(除了大小写):你会丢失大约30-40个呼叫(大约5%).所以可能在您的应用程序中,您非常接近极限.顺便说一句,我注意到之间的骤升-Xss256k-Xss260k(上1.8.0_40测试):

          St/0  St/1  St/2  St/3  St/4  In/0  In/1  In/2  In/3  In/4
-Xss256k  2724  2476  2270  2095  1945  2476  2270  2095  1945  1816
-Xss260k  4493  3228  2959  2731  2536  3228  2959  2731  2536  2367
Run Code Online (Sandbox Code Playgroud)

所以你可以尝试增加堆栈大小-Xss260k,它应该足以完成你的任务.

顺便说一句,32位JVM允许使用相同的更多调用-Xss228k:

          St/0  St/1  St/2  St/3  St/4  In/0  In/1  In/2  In/3  In/4
7u67_32b  7088  5078  4655  4297  3990  5078  4655  4297  3990  3724
7u67_32b  6837  5092  4667  4308  4001  5092  4667  4308  4001  3734
Run Code Online (Sandbox Code Playgroud)

因此,您也可以从32位Java-7切换到64位Java-8.在这种情况下,当然需要更多的堆栈空间,因为即使使用压缩的OOP,堆栈中的指针似乎也是64位,因此占用更多空间.