Java program that calls external program behaving asynchronously?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
When Java launches another program, the call often feels asynchronous because ProcessBuilder.start() returns as soon as the child process is created. That is normal behavior. The real debugging task is to separate three cases: Java never waited, Java waited for the wrong process, or Java blocked because the child process output was not drained.
What start() Actually Guarantees
ProcessBuilder.start() guarantees that the operating system started a child process. It does not guarantee that the child has finished.
After this line, Java continues immediately. If your main thread exits or runs more logic right away, that is expected. Launching a process and waiting for it are two separate steps.
Use waitFor() When You Need Synchronous Behavior
If the external program must finish before Java continues, call waitFor():
This is the correct synchronous pattern for ordinary command-line tools. If this does not solve the problem, the next question is whether the external program itself is detaching into the background.
Java Can Only Wait for the Process It Started
Some commands are wrappers. They spawn another process and then exit. Shell scripts that use &, launcher executables, or programs that daemonize themselves all behave this way.
In that situation, waitFor() is not wrong. It waits for the original child process, and that process truly ends quickly. The long-lived work continues in a grandchild process that Java does not manage directly.
That distinction matters because the fix is not in Java code. The fix is in the command or wrapper script:
- remove backgrounding logic
- invoke the real executable directly
- change the wrapper so it stays attached until the work is done
If you need job-level tracking rather than process-level tracking, design that explicitly instead of assuming waitFor() can see detached descendants.
Always Handle Output Streams
Another common reason a subprocess seems to behave strangely is blocked standard output or standard error. A child process can stall if Java never consumes its output and the OS pipe buffer fills up.
For simple tools, inheritIO() is often enough:
If you need programmatic access, read the streams yourself:
This pattern is especially important for chatty tools.
Make Asynchronous Execution Explicit
Sometimes asynchronous behavior is the goal. In that case, do not fake synchronicity. Launch the process, keep the Process object, and attach completion handling:
This makes the program structure honest. You are not ignoring lifecycle management. You are managing it asynchronously on purpose.
Common Pitfalls
- Expecting
start()to block until the child process completes. - Calling
waitFor()on a launcher process that immediately spawns and detaches another program. - Ignoring stdout and stderr, which can cause the child to block.
- Using shell wrappers when Java could invoke the target program directly.
- Treating accidental async behavior as acceptable instead of designing the process lifecycle explicitly.
Summary
- '
ProcessBuilder.start()launches a child process and returns immediately.' - Use
waitFor()when Java must wait for that child to exit. - If waiting still finishes too early, the external program may be detaching another process.
- Drain stdout and stderr or use
inheritIO()to avoid blocked subprocesses. - When asynchronous execution is intentional, model it explicitly with
Process.onExit()or a managed executor.
Related reading
- Java properly closing sockets for multi threaded servers
- Java Singleton and Synchronization
- Java Synchronized Block for .class
- Java synchronized method
- Java project in Eclipse The type java.lang.Object cannot be resolved. It is indirectly referenced from required .class files
- Java recommended solution for deep cloning/copying an instance
- Java synchronized method lock on object, or method?
- Java synchronized method lock on object, or method?

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.