Ogen Ogen - 4 months ago 8
Java Question

Executing Java line by line

I'm trying to set up my java code such that it can be potentially stopped after any point of code execution.

I was thinking of putting all of my code inside a thread and calling

on it when I want it to stop. Note that this method will only cause the code to throw an
if any thread blocking method is being run (Like
, etc.). Otherwise it will just set the interrupted flag and we have to check it via the
after every line.

So now all I need to do is insert the following code...

if (myThread.isInterrupted()) {

after every line of code. If my java code was stored in a
, how can I insert this line of code after every point of execution of my code?

I was thinking of using the split method on semicolons and inserting the thread code between every element in the resulting array but it doesn't work because, for example, for loops have semicolons that don't represent the end of a statement. I think I would also have to split on closing curly braces too because the also represent the end of a code statement.

EDIT: solution attempt:

final String javaCode = "if (myString.contains(\"foo\")) { return true; } int i = 0;";
final String threadDelimiter = "if (thisThread.isInterrupted()) { System.exit(0); }";
final StringBuffer sb = new StringBuffer();

for (int i = 0; i < javaCode.length(); i++) {
final char currChar = javaCode.charAt(i);

if ("{};".contains(currChar + "")) {


This code is almost correct but it would not work for any sort of loops that use semicolon. It also wouldn't work for for loops that don't have braces.


First off, if your goal is to trigger System.exit() there's no need to inject such calls into another thread and then interrupt that thread; just call System.exit() where you would have called otherThread.interrupt(); and the process will exit just as quickly.

Second, your plan will not accomplish your goal. Suppose you added your interrupt-then-exit code around this statement:

new Scanner(System.in).next();

If nothing is being written to the program's stdin this statement will block indefinitely, and will not respect thread interruption. There are countless other examples of similar code snippets that will cause a thread to block. Your interrupted check may never be reached, no matter how granularity you inject it.

Third, manipulating source code as a string is a path down which madness lies. There exist standard structured tools to parse Java syntax into structured data types that you can safely manipulate. If you must do source code manipulation use the right tools.

Fourth, there's no particular reason you need to interact with source code to simply inject additional commands; compile the source and use bytecode injection to inject your commands directly. Bytecode has a much more limited syntax than Java source, therefore it's easier to reason about and mutate safely.

All of that aside, however, you simply don't need to do any of this

It sounds like your goal is to execute some unknown snippet of Java code but be able to cause the process to stop at any time. This is exactly what your operating system is designed to do - manage process executions. To that end POSIX provides several standard signals you can send to a process to gracefully (or not-so-gracefully) cause that process to terminate. Sending a Java process a SIGINT (Ctrl-C), SIGTERM, or SIGHUP will cause the JVM to initiate its shutdown sequence, effectively triggering a System.exit().

There are two key steps that occur when the JVM shuts down:

In the first phase all registered shutdown hooks, if any, are started in some unspecified order and allowed to run concurrently until they finish. In the second phase all uninvoked finalizers are run if finalization-on-exit has been enabled. Once this is done the virtual machine halts.

In other words, as long as you prevent the code you're running from registering malicious shutdown hooks or calling runFinalizersOnExit() sending these signals will cause the JVM to terminate promptly.

If even that isn't acceptable for your use case send a SIGKILL instead; the OS will immediately cause the process to terminate, without giving it a chance to run shutdown hooks or finalizers. You can also call Runtime.halt() from within the JVM to accomplish roughly the same thing.