java.lang.StackOverflowError while doing deep recursion with Java 1.6 and Windows 7 OS

做~自己de王妃 提交于 2019-12-22 10:14:33

问题


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 Objects, 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!