3

I'm trying to implement a certain puzzle solver in Java given an initial state and certain goal specifications. For various reasons, I cannot share the actual code, and that likely doesn't matter anyway. The basic algorithm is that it uses recursive depth-first search to try to find a step-by-step solution to solving the puzzle. One note is that it is possible for the goal specifications to be unreachable from the initial state. Obviously the recursion can be very deep and is very intensive on the stack

The code works flawlessly on small puzzles, and works on some larger ones. I'm running a collection of test cases with large inputs. On my Macbook, certain test cases pass, but on another computer, these same test cases, on the same code, fail due to a StackOverflowError. The other computer runs faster so it'd be in my best interests to get those test cases working like they do on my Macbook. You can safely dismiss the possibility of the Stack Overflow Error being a result of infinite recursion - I know it's because the stack is running out.

I ran the following commands:

On my macbook:

$ java -XX:+PrintFlagsFinal -version | grep -iE 'heapsize|permsize|threadstacksize'
uintx AdaptivePermSizeWeight                    = 20              {product}           
 intx CompilerThreadStackSize                   = 0               {pd product}        
uintx ErgoHeapSizeLimit                         = 0               {product}           
uintx InitialHeapSize                           = 0               {product}           
uintx LargePageHeapSizeThreshold                = 134217728       {product}           
uintx MaxHeapSize                               = 132120576       {product}           
uintx MaxPermSize                               = 85983232        {pd product}        
uintx PermSize                                  = 21757952        {pd product}        
 intx ThreadStackSize                           = 1024            {pd product}        
 intx VMThreadStackSize                         = 1024            {pd product}   

On the other computer (which uses Ubuntu) I ran:

java -XX:+PrintFlagsFinal -version | grep -iE 'HeapSize|PermSize|ThreadStackSize'
 intx CompilerThreadStackSize                   = 0               {pd product}        
uintx ErgoHeapSizeLimit                         = 0               {product} 
uintx HeapSizePerGCThread                       = 87241520        {product}           
uintx InitialHeapSize                          := 526385152       {product}           
uintx LargePageHeapSizeThreshold                = 134217728       {product}           
uintx MaxHeapSize                              := 8420065280      {product}           
 intx ThreadStackSize                           = 1024            {pd product}        
 intx VMThreadStackSize                         = 1024            {pd product}   

So, what's going wrong here? Why does my macbook run the tests without incident while the other machine stack overflows?

I'm not sure what additional information would be helpful here, but I can provide it if necessary.

EDIT: java -version for both:

On Macbook:

java version "1.6.0_32"
Java(TM) SE Runtime Environment (build 1.6.0_32-b05-420)
Java HotSpot(TM) 64-Bit Server VM (build 20.7-b02-420, mixed mode)

On Ubuntu:

java version “1.8.0_45”
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
dimo414
  • 47,227
  • 18
  • 148
  • 244

1 Answers1

1

Even with the same stack size the actual usage of stack might be different. It may depend on:

  • JVM vendor
  • JVM version (even changes in minor version might lead to different stack usage)
  • Operating System
  • Whether method is interpreted, JIT-compiled by C1 or C2 compiler (C2-compiled method usually eats less stack).
  • Some random startup conditions (even on the same box the stack usage might be different on different launches).

You may check this answer and this answer for more details. The recommendation is to rewrite your algorithm removing the stack pressure. For example, using ArrayDeque to represent the stack of states and replace recursion with the loop.

Community
  • 1
  • 1
Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334