Back to our regularly scheduled programming...
I'm not sure what the API for a subprocess-like utility should be.
You mentioned subprocess.communicate, but that's actually blocking.
Maybe two top-level functions, following the existing pattern:
system.util.runBlocking
system.util.runAsync
Where runBlocking returns a ProcessResult or something similar with information about the run including stdout and stderr.
runAsync would return a CompletableFuture wrapper, with maybe a method to inject data into stdin? Or you could runAsync().wait() and get the ProcessResult?
I'd have to think about the API a little more. If it gets somewhere stable enough, maybe I'll push to make it first party; I think that's something lots of people would find useful.