使用java 1.6和Windows 7操作系统执行深度递归时出现java.lang.StackOverflowerError
我有一个程序,在执行时会运行到一个非常深的递归中。在这个过程中,我得到了使用java 1.6和Windows 7操作系统执行深度递归时出现java.lang.StackOverflowerError,java,memory-management,stack-overflow,Java,Memory Management,Stack Overflow,我有一个程序,在执行时会运行到一个非常深的递归中。在这个过程中,我得到了java.lang.StackOverflowerError,我的应用程序冻结了。我正在使用JDK1.6和Windows7操作系统 奇怪的是,在使用Java 1.5和Windows XP运行我的应用程序时,我没有用相同的代码库获得这个StackOverflowerError。我知道默认堆栈大小因平台和操作系统而异。但在Java1.5和WindowsXP中,我使用-Xss命令将堆栈大小设置为256k,但没有得到这个错误。在Wi
java.lang.StackOverflowerError
,我的应用程序冻结了。我正在使用JDK1.6和Windows7操作系统
奇怪的是,在使用Java 1.5和Windows XP运行我的应用程序时,我没有用相同的代码库获得这个StackOverflowerError
。我知道默认堆栈大小因平台和操作系统而异。但在Java1.5和WindowsXP中,我使用-Xss
命令将堆栈大小设置为256k,但没有得到这个错误。在Windows7OS和Java1.6中使用相同的256k时,我遇到了这个错误
堆栈大小为256k,我的应用程序在Windows XP中运行时没有任何问题,并且在Windows 7操作系统中抛出stackoverflower错误
因此,请给出从Windows 7操作系统到Windows XP线程堆栈大小的差异信息???我认为答案是,JDK 1.5忽略将默认堆栈大小设置为特定值。比方说,如果您有一个默认的堆栈大小512K,并且(您相信)您将它设置为256K,那么最后它的值仍然是512K。使用jdk6时,您还可以将默认大小设置为256K,但在这里它确实会有这个值。这可能就是为什么您的Windows 7(更早)出现错误的原因
查看此-Xss默认值表:
Platform Default
----------------------------------
Windows IA32 64 KB
Linux IA32 128 KB
Windows x86_64 128 KB
Linux x86_64 256 KB
Windows IA64 320 KB
Linux IA64 1024 KB (1 MB)
Solaris Sparc 512 KB
在这里您可以看到,默认值与您运行的平台不同
见:
此外,由于在一个系统上得到的是stackoverflowerrror
,而在另一个系统上没有,因此32位VM将使用4字节内存存储地址。64位虚拟机将以8字节存储相同的数据!因此,假设您将堆栈大小值设置为256K(是的,它是KB),32位系统(可能是您的XP系统)可以在其堆栈内存中存储65536个地址。64位系统(Windows 7系统)只能存储32768个地址。这可能是这两个系统之间的问题
通常,Java对象在32位虚拟机中消耗的内存大小与在64位虚拟机中消耗的内存大小相同。显然,如果您有一个对象
,它引用了100个其他对象
s,那么在64位JVM上,它会将主对象
的大小增加400字节
此外,据说:
请注意,在某些版本的Windows上,操作系统可能会对线程进行取整
堆栈大小使用非常粗的粒度。如果请求的大小为
小于默认大小1K或更大,堆栈大小向上舍入
违约;否则,堆栈大小将向上舍入为倍数
1兆字节
64k是每个线程允许的最小堆栈空间量
见:
不幸的是,我没有找到任何具体的解释,即粗粒度是如何表达的
尝试在两个平台上运行以下示例程序,以猜测堆栈大小之间的差异:
public class StackOverflowTest {
public static void main(String[] args) {
recurse(0);
}
private static void recurse(int i) {
try {
recurse(++i);
} catch (StackOverflowError e) {
System.out.println(i);
System.exit(0);
}
}
}
我的机器上的结果是:
Windows 7 (64-bit)
Stack calls Java Stack size
------------------------------------------
11424 JDK 5 64-bit default
11424 JDK 5 64-bit -Xss256K
11424 JDK 5 64-bit -Xss1024K
6260 JRE 6 32-bit default
4894 JRE 6 32-bit -Xss256K
35405 JRE 6 32-bit -Xss1024K
10448 to 10468 JDK 7 64-bit default
2255 to 2274 JDK 7 64-bit -Xss256K
10448 to 10468 JDK 7 64-bit -Xss1024K
10396 to 41894 JDK 8 64-bit default
2203 to 4590 JDK 8 64-bit -Xss256K
10396 to 41894 JDK 8 64-bit -Xss1024K
(如果列表可以从您正在运行的其他系统扩展,那就太好了!)
正如您所看到的,堆栈大小完全是个谜。事实上,不同的Java版本在堆栈内存中消耗不同的空间
此外,如果您使用-Xss
设置堆栈大小,则在Java 5版本中将忽略该值
对于JDK 7,您不会总是得到与其他版本相同的结果。JDK 8也是如此,其范围相差很大
也许你可以自己弄清楚,如果它只是在你自己的系统上有轻微的不同或者没有
进一步阅读:
此规范允许Java虚拟机堆栈为
一个固定的大小或大小,可以根据
计算。如果Java虚拟机堆栈的大小固定,
可以选择每个Java虚拟机堆栈的大小
在创建堆栈时独立运行
所以,问题是,什么是动态扩展
然后,我在源代码中发现了一个bug,如果您运行的是早期的Java 6版本,则可能会对此感兴趣:
你能分享你的代码吗?嗨。这不是复制品,我的朋友。我的问题是,我的应用程序在WInodws Xp中运行时没有任何问题,堆栈大小为256k。但在Windows7中,它给了我相同堆栈大小256k的堆栈溢出错误。在Windows7中通过-Xss增加堆栈大小可以解决这个问题。但奇怪的是,为什么它不能在Windows7中以相同的堆栈大小工作?有人知道什么是256k单元吗?字节还是帧?这可能会有所不同,因为这样一来,64位系统上的帧可能会因为指针大小更大而更大。因此,假设单位为byte.Hi,256kB中可以容纳更少的帧。谢谢你的回复。现在很清楚,默认堆栈大小将因平台而异。但若我们在WindowsXP和Windows7中设置相同的堆栈大小,那个么应用程序在WindowsXP中运行成功,而在Windows7中运行失败。有什么理由吗。非常感谢您对此的回复。提前谢谢。我猜你的Windows7系统是64位版本,XP是32位版本。因此,这可能会改变内存的使用方式!我已经扩展了我的答案来区分32位和64位系统。您对32位和64位版本之间差异的解释对我来说是有意义的,可能是事实。但是,我在Windows XP和Windows 7上都使用32位版本。在这种情况下,内存消耗会产生任何影响??我已经更改了答案,并添加了一个示例程序,您可以尝试在这两种平台上执行。也许,你能想出办法!事实上,你的问题很好;)