问题
I have a program which will run into a very deep recursion while executing. In middle of this, I am getting java.lang.StackOverflowError
and my application freezes. I am using JDK 1.6 and Windows 7 OS.
Strange thing here is, I am not getting this StackOverflowError
with same code base while running my application with Java 1.5 and Windows XP. I understood that default stack size will differ from platform to platform and OS to OS. But with Java 1.5 and Windows XP, I set stack size of 256k using -Xss
command and not getting this error. With same 256k in Windows 7 OS and Java 1.6, I am getting this error.
With stack size of 256k, my application is running without any issue in Windows XP and it's throwing a StackOverflowError
in Windows 7 OS.
So please give any information how thread stack sizes will differ from Windows 7 OS to Windows XP??
回答1:
I think the answer is, that the JDK 1.5 ignores setting the default stack size to a specific value. Say, if you have a default stack size of 512K and (you believe that) you set it to 256K, finally it will still have a value of 512K. With the JDK 6 you also set the default size to 256K, but here it really will have this value. That could be the reason, why your Windows 7 is getting the error (earlier)!
Look at this -Xss Default Values table:
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
Here you can see, that the default values differ to the platform you're running on.
See: http://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/jrdocs/refman/optionX.html#wp1024112
Furthermore, because you're getting a StackOverflowError
on one system, but not the other, a 32-bit VM will store addresses with 4 bytes of memory. A 64-bit VM will store the same with 8-bytes! So, assuming you set the stack size value to 256K (yes, it's kBytes), a 32-bit system (probably your XP system) can store 65,536 addresses in its stack memory. A 64-bit system (your Windows 7 system) is only be able to store 32,768 addresses. This could be the issue between these two systems.
In general, Java objects consuming the same size of memory in a 32 as in a 64-bit VM. Obviously, if you have an Object
which is referencing to 100 other Object
s, it will increase the size of the main Object
by 400 bytes on a 64-bit JVM.
Additionally it is said:
Note that on some versions of Windows, the OS may round up thread stack sizes using very coarse granularity. If the requested size is less than the default size by 1K or more, the stack size is rounded up to the default; otherwise, the stack size is rounded up to a multiple of 1 MB.
64k is the least amount of stack space allowed per thread.
See: http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#threads_oom
Unfortunately, I didn't find any concrete explanation, how the coarse granularity is being expressed.
Try to run the following sample program on both platforms to guess, how much the stack sizes differ between each other:
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);
}
}
}
The results on my machine are:
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
(It would be great, if the list can be extended from other systems you're running on!)
As you can see, the stack sizes are a complete mystery. It can be the fact, that the different Java versions consume different spaces in the stack memory.
Furthermore, if you set the stack size with -Xss
, the value will be ignored on a Java 5 release.
With the JDK 7, you're not getting always the same result like on the other releases. The same goes to the JDK 8, where the ranges differ substantially.
Perhaps you can figure out yourself, if it only differs slighty or not on your own systems.
Further reading: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.5.2
This specification permits Java Virtual Machine stacks either to be of a fixed size or to dynamically expand and contract as required by the computation. If the Java Virtual Machine stacks are of a fixed size, the size of each Java Virtual Machine stack may be chosen independently when that stack is created.
So, the question is, what is meant by dynamically expand?
Then I discovered a bug in the sources, that could be of interest, if you're running on an earlier Java 6 release:
http://bugs.java.com/view_bug.do?bug_id=6316197
来源:https://stackoverflow.com/questions/21404616/java-lang-stackoverflowerror-while-doing-deep-recursion-with-java-1-6-and-window