VM and OS abstractions have been so successful that you can go a whole career without talking directly to hardware, but remember, at the bottom of the abstraction pile something has to resolve down to voltages on wires. Function calls, method names, and JSON blobs don't do that. So what does? What abstraction bridges the gap between ASCII spells and physical voltages?
Address space. I/O ports exist, but mostly for legacy/standard reasons. Address space is the versatile and important bridge out of a VM and into the wider world. It's no mistake that C and C++ let you touch it, and it's no mistake that other languages lock it away. Those are the correct choices for their respective abstraction levels.