If you can edit your production code and run it somewhere; you could modify the code so that a stacktrace is dumped at a specific recursion depth. That allows you to "see the bottom" of the stacktrace.
Of course, you need to modify your production code in a compatible way (eg., adding a "depth" parameter to the foo
method is not allowed- since this affects your clients).
See eg. the following code; we store the recursion depth in a thread-local variable.
package lang;
/**
* run with -Dmy.debug.dump.enabled=true
*/
public class StackOverflowTest {
public static void main(String[] args) {
try {
StackOverflowTest o = new StackOverflowTest();
o.foo();
} catch (StackOverflowError err) {
System.out.println("err: StackOverflowError");
}
}
private static ThreadLocal<Integer> recurseCount = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0;
};
};
private static final boolean DUMP_ENABLED;
static {
String sysprop = System.getProperty("my.debug.dump.enabled");
DUMP_ENABLED = sysprop!=null && "true".equals(sysprop);
}
// or set it via system properties
private static final int DUMP_ON_RECURSION_NUM=4;
class MyRecurseDump extends Exception {
public MyRecurseDump(String msg) {
super(msg);
}
private static final long serialVersionUID = 1L;
}
private void foo() {
try {
if (DUMP_ENABLED) {
recurseCount.set(recurseCount.get()+1);
if (recurseCount.get()==DUMP_ON_RECURSION_NUM) {
new MyRecurseDump("foo: reached num="+DUMP_ON_RECURSION_NUM+" recursion depth")
.printStackTrace(System.err);
}
}
// put foo code here
int x;
foo();
// end of foo code
//*********************************************
}
finally {
if (DUMP_ENABLED) {
recurseCount.set(recurseCount.get()-1);
}
}
}
}
Running it with java -Dmy.debug.dump.enabled=true lang.StackOverflowTest
, the output is:
lang.StackOverflowTest$MyRecurseDump: foo: reached num=4 recursion depth
at lang.StackOverflowTest.foo(StackOverflowTest.java:44)
at lang.StackOverflowTest.foo(StackOverflowTest.java:53)
at lang.StackOverflowTest.foo(StackOverflowTest.java:53)
at lang.StackOverflowTest.foo(StackOverflowTest.java:53)
at lang.StackOverflowTest.main(StackOverflowTest.java:11)
err: StackOverflowError
It can be tweaked in a number of ways (change recursion depth in example); or only perform a single dump across your whole program (because you could have multiple dumps).