Is it possible to save the state of the call stack during execution and later restore the stack to that state, restarting at the top-most method call?
-
Why would you want to do that? – arshajii May 21 '14 at 13:37
-
I am executing an algorithm which can be interrupted because it realises some earlier information it relied on is now out of date. Rather than restart from the very beginning I would like to restart from the method where it used the out of date information. I am only concerned in this question about restoring the call stack, I am not worried about how this affects the heap. – user973758 May 21 '14 at 13:47
-
What do you mean by "Restore the state of the stack"? Once your program has moved on with its execution, the previous stack is no longer relevant. – David says Reinstate Monica May 21 '14 at 13:55
-
1By "restarting at the top-most method call", what are you trying to do that is different from just calling that method again? – Dan Getz May 21 '14 at 13:59
-
If I just call the method again then I am losing the context of where the method was called from, and where it should return its value to – user973758 May 21 '14 at 14:01
-
1I have had a look at your other questions and it seems that many of them has a kind of the *hacking undertone*. I'd recommend you to use more "standard" ways instead. You would produce better maintainable code. You would also learn something which is more persistent. The hacking tricks you seem being learning are not long-lasting, they are bound to the concrete technologies. Once the technologies change, you will be just an old hippie recollecting the good old days :) – Honza Zidek May 21 '14 at 14:33
-
@HonzaZidek - well done for seeing beyond the question! However, hacking is subjective. Hacking is a very good tool in your toolbox. It takes a few years of experience to actually know the difference between writing in-vogue code and code that totally bends the rules of the norm to suit your purpose. A hack is usually when a programmer looks at code and doesn't understand what's going on, because of the unorthodox nature of the code. Not a bad thing. It's a bad thing when you leave hacky code for someone else to maintain. Who wrote that crap? Wow. Did I? Lesson learnt. – KRK Owner May 08 '18 at 21:27
5 Answers
I strongly suggest to change your paradigm. Instead of manipulating the call stack (and very probably corrupting your JVM), think about incorporating the "call stack" somehow in your algorithm.
You may use the Strategy/Command/Undo design pattern and store the objects to your own logical stack, over which you have full control.
There is a related question Way to go from recursion to iteration with a lot of good answers.

- 1
- 1

- 9,204
- 4
- 72
- 118
-
1Thank you for bringing some *Keep It Simple Stupid* common sense to this question – Nick Holt May 21 '14 at 14:19
You can restart from a specific call stack with normal program flow control, instead of messing directly with call stacks. One way is with exceptions:
Result findResult() {
while (true) {
Data data = getData();
try {
return processData(data);
} catch (OutOfDateException e) {
/* fall through */
}
}
}
Result processData(Data data) throws OutOfDateException {
/* ... */
processData2(otherData)
/* ... */
}
IntermediateResult processData2(OtherData otherData) throws OutOfDateException {
/* ... */
if (myDataWasTooOld())
throw new OutOfDateException();
/* ... */
}
In the example, if processData2()
throws the exception, the same call stack (processData2()
called from processData()
) is recreated with a new value for data
.

- 8,774
- 6
- 30
- 64
I think you're looking for something Continuations based... Java Flow is an old project, but I think it does exactly what you ask - saves stack frames as a Continuation object, using bytecode "magic" - that is, some extra code is weaved into your code to allow for stack frames to be saved into an object.
http://commons.apache.org/sandbox/commons-javaflow/tutorial.html

- 762
- 7
- 16
Saving the current call stack is quite simple. The Thread
class has some stack trace oriented functions. Most likely this is what you are looking for -
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
And now you have saved your stack trace, to be used later however you will. Im not sure what you mean by restore the stack trace though.

- 19,209
- 22
- 79
- 122
-
What OP is trying to do goes far beyond accessing the stacktrace, he is actually trying to manipulate the stack (on the stack, there is not only the stack trace information, but also the arguments to methods). Also he not only wants to read that information, but also write. – kutschkem May 21 '14 at 14:14
It is definitely possible to watch the stack trace. I have done this before after doing too much shell scripting and getting a response for every line of code. What I did was to create a listener thread that is a child of the main thread.
Something like this:
public class Debugger implements Serializable {
private static final long serialVersionUID = 1L;
private Thread parent;
private String packageName;
private File outputFile;
private boolean alive;
public Debugger(Thread parent, String packageName, File outputFile) {
this.parent = parent;
this.packageName = packageName;
this.outputFile = outputFile;
alive = true;
}
public void run() throws FileNotFoundException {
PrintStream ps = new PrintStream(outputFile);
alive = true;
String lastClassName = "";
while (parent.isAlive() && alive) {
for (StackTraceElement ste : parent.getStackTrace()) {
if (ste.getClassName().startsWith(packageName)) {
if (!ste.getClassName().equals(lastClassName)) {
ps.println(ste.toString());
lastClassName = ste.getClassName();
}
break;
}
}
}
ps.close();
}
public void kill() {
alive = false;
}
}
If you create this object at the beginning of the code you would like to debug, it will write to your file every new method in your package prefix/substring that is called. Then just call kill() at the code you want to watch for the stack trace. There is a chance that it will miss methods if your main thread/code runs faster than this thread, but it will more than likely catch everything.
You could include a timestamp (new Date()) there to see how long your method calls take to return as well.
In order to get what you wanted, you could save these method calls within the stack trace and use reflection to invoke the methods again later. However, I do think that would be a bad practice.

- 401
- 2
- 11