flawopen.com/Command Injection/Java Runtime.exec
Safer than you'd expect by default — the single-string overload does its own basic tokenizing without invoking a shell — but building that string by concatenating untrusted input can still let an attacker inject extra arguments, and ProcessBuilder with an explicit argument array is the more robust choice either way.
Runtime.getRuntime().exec( "convert " + filename + " out.png" );
new ProcessBuilder( "convert", filename, "out.png" ).start();
Unlike Python's os.system() or Node's exec(), Java's single-string Runtime.exec(String) does not invoke a shell — it splits the string on whitespace itself. This means classic shell-metacharacter chaining (;, |) doesn't work the same way it does with those. It's still risky, though: untrusted input can inject additional whitespace-separated arguments the program wasn't meant to receive, which can be just as dangerous depending on what the target program does with extra arguments. ProcessBuilder with an explicit array removes this ambiguity entirely — each array element is exactly one argument, regardless of what characters or whitespace it contains.
No — "doesn't invoke a shell" is not the same as "safe." Extra-argument injection is a real, documented risk category of its own. Use ProcessBuilder with an array for anything involving untrusted input.