iOS simulator can leverage the host's macOS libraries and kernel. Android doesn't share anything at all with Windows or macOS, and shares only the kernel at best with Linux. The best you can hope for is running Android in a container on a host Linux system, or via WSL. Unless you can get containers running natively on macOS, or run a Linux kernel a la WSL, there will need to be a layer of emulation to run Android.
While the iOS Simulator does share the host kernel it does not share libraries. It is effectively a separate userspace, with its own launchd_sim, its own mach bootstrap namespace, and so on.
The only exception to that is libsystem_{pthread,kernel,platform} because those form the kernel's ABI boundary. Libraries like libc, libdispatch, et al are the iOS build and use the iOS ABI.
Thanks for the clarification, I was under the impression that they shared libraries like the browser engine and what not. Not sure where I got that misconception.
An Android app is a Java app using a set of special APIs. Why can't it run on a host JVM given some libraries implementing the same APIs? I'm not interested in the NDK.
> Why can't it run on a host JVM given some libraries implementing the same APIs?
That's a hideously huge API surface to double-implement - with a new and unique set of bugs reducing it's usefulness in CI builds - for slightly improved performance in a relatively niche dev edge case (!ndk android dev without android hardware.) You'd also need to skip conversion to DEX format (or convert back) to run on a standard JVM.
But your suggestion isn't technically impossible. You could (re)implement the subset of APIs your application happens to use yourself, if you really wanted to go down that route - which by virtue of being a much smaller subset of the APIs than the entire Android Java API surface, wouldn't even be practically impossible.